﻿Imports Commander_Wars.Spieletools
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX
''' <summary>
''' This AI Sourcecode is in English and with some more Comments than usual.
''' You're fighting you're loosing here.=D
''' Robosturm's Special AI...
''' PFS=Path-Findinf-System.
''' This AI tries to create Armies
''' And tries to defeat you in new ways
''' First Turn Move=We try to do a useful move in this Turn
''' Far Away Turn Move=We move our Unit so that we can do a useful Move in X Turns. (E.G. Capturing, Attacking)
''' Special CO Behaviour=Here stands Code that is written for a couple of CO's
''' </summary>
''' <remarks></remarks>
Public Class AI_Heavy
    Inherits ObjektKI
    '(Attack= 48 (163 (Indirect)) / 0 Capture= 87 / 1 Build= 40 (998) (1452) / -16
    'CounterValue (253 / 0)
    'Max Time 2 s 441 ms
#Region "Constant Values or Calculation Functions"
    ''' <summary>
    ''' If an Action is bad we set the Score to this Value
    ''' </summary>
    ''' <remarks></remarks>
    Const BadActionScore As Integer = Integer.MinValue
    ''' <summary>
    ''' Calculates the Minimum Score for Explosions and Silo launching
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetMinimalExplosionScore() As Integer
        Return 8
    End Function
    ''' <summary>
    ''' This Turns True if new Units were build or placed by COP's.
    ''' No thinking if the new Units could move or not when placed by COP's.
    ''' </summary>
    ''' <remarks></remarks>
    Dim newUnitsArrived As Boolean = True
    ''' <summary>
    ''' Are we in the second Turn Round?
    ''' </summary>
    ''' <remarks></remarks>
    Dim SecondTurn As Boolean = False
#End Region
#Region "Test and Show Functions"
    'No comments here as this function is not used in code later on.
    ''' <summary>
    '''Shows the Influence Map 
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ShowInfluence()
        If Not (DataSettings.draw3D Or DataSettings._2D_3D_Malen) Then
            If VirtualMap IsNot Nothing Then
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                        If VirtualMap(X, Y) IsNot Nothing Then
                            Dim Player As Integer = 0
                            Dim Influence As Single = 0
                            Dim Influence2 As Single = 0
                            For I = 0 To VirtualMap(X, Y).Influences.Count - 1
                                If VirtualMap(X, Y).Influences(I) > Influence Then
                                    Influence2 = Influence
                                    Influence = VirtualMap(X, Y).Influences(I)
                                    Player = I
                                End If
                            Next
                            If Influence <= 1 And Influence >= 0 Then
                                If Influence2 <= 1 And Influence2 >= 0 Then
                                    Grafikengine.fillRect(X * Hauptmenue.Feldbreite - Hauptmenue.Feldbreite / 2 + Objektverwalter.Spielfeld.BildschirmKooX, Y * Hauptmenue.Feldbreite - Hauptmenue.Feldbreite / 2 + Objektverwalter.Spielfeld.BildschirmKooY, Hauptmenue.Feldbreite, Hauptmenue.Feldbreite, Color.FromArgb((Influence - Influence2) * 180 + 30, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.R, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.G, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.B))
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
    End Sub
    ''' <summary>
    '''Shows the Frontlines
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ShowFrontlines()
        If Not (DataSettings.draw3D Or DataSettings._2D_3D_Malen) Then
            If VirtualMap IsNot Nothing Then
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                        If VirtualMap(X, Y) IsNot Nothing Then
                            If VirtualMap(X, Y).FrontField.Count > 0 Then
                                Dim Player As Integer = VirtualMap(X, Y).GetPlayerowner
                                Grafikengine.fillRect(X * Hauptmenue.Feldbreite - Hauptmenue.Feldbreite / 2 + Objektverwalter.Spielfeld.BildschirmKooX, Y * Hauptmenue.Feldbreite - Hauptmenue.Feldbreite / 2 + Objektverwalter.Spielfeld.BildschirmKooY, Hauptmenue.Feldbreite, Hauptmenue.Feldbreite, Color.FromArgb(160, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.R, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.G, Objektverwalter.Spielfeld.Spieler(Player + 1).Farbe.B))
                            End If
                        End If
                    Next
                Next
            End If
        End If
    End Sub
#End Region
#Region "Virtual Battle Map"
    ''' <summary>
    ''' A virtual Map used to represent influence and other Stuff on this Field.
    ''' </summary>
    ''' <remarks></remarks>
    Public VirtualMap As VirtualField(,)
    Class VirtualField
        ''' <summary>
        ''' The several Influences by each player.
        ''' </summary>
        ''' <remarks></remarks>
        Public Influences As New List(Of Single)
        ''' <summary>
        ''' Contains to which Players this is a Frontfield the owner can be get by GetPlayerOwner.
        ''' </summary>
        ''' <remarks></remarks>
        Public FrontField As New List(Of Integer)
        Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Player As ObjektSpieler, ByVal AIDatabase As Database)
            For I = 1 To Objektverwalter.Spielfeld.Spieler.Count - 1
                Influences.Add(0)
            Next
            Me.X = X
            Me.Y = Y
            Dim Enemy As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
            If Enemy IsNot Nothing Then
                If Enemy.GetSpieler.Team <> Player.Team Then
                    Me.Enemy = Enemy
                    EnemyPFS = New Wegsuchsystem(Enemy, Enemy.Bewegungspunkte * AIDatabase.GetPlayerData(Enemy.Spieler).PlayerMoves, , Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen, False)
                End If
            End If
        End Sub
        ''' <summary>
        ''' Checks which player has the biggest Influence and returns this player
        ''' -1 nobody owns it.
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetPlayerowner() As Integer
            Dim Playerowner As Integer = 0
            'Loop through all Players and compare Percentages
            For I = 1 To Influences.Count - 1
                If Influences(I) > Influences(Playerowner) Then
                    Playerowner = I
                End If
            Next
            If Influences(Playerowner) = 0 Then Return -1
            Return Playerowner
        End Function
        ''' <summary>
        ''' Enemy Unit on this Field
        ''' </summary>
        ''' <remarks></remarks>
        Public Enemy As ObjektEinheit = Nothing
        ''' <summary>
        ''' The PFS of this Unit on this Field!
        ''' </summary>
        ''' <remarks></remarks>
        Public EnemyPFS As Wegsuchsystem = Nothing
        ''' <summary>
        ''' X Position
        ''' </summary>
        ''' <remarks></remarks>
        Public X As Integer
        ''' <summary>
        ''' Y Position
        ''' </summary>
        ''' <remarks></remarks>
        Public Y As Integer
        Public Sub UpdateField(ByVal Player As ObjektSpieler, ByVal AIDatabase As Database)

            Dim Enemy As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
            If Enemy IsNot Nothing Then
                If Enemy.GetSpieler.Team <> Player.Team Then
                    Me.Enemy = Enemy
                    EnemyPFS = New Wegsuchsystem(Enemy, Enemy.Bewegungspunkte * AIDatabase.GetPlayerData(Enemy.Spieler).PlayerMoves, , Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen, False)
                End If
            Else
                Enemy = Nothing
                EnemyPFS = Nothing
            End If
        End Sub
    End Class
    ''' <summary>
    ''' Initializes the Virtual Battlemap
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub CreateVirtualMap()
        'Ini Virtual Map
        ReDim VirtualMap(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Hoehe - 1)
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                VirtualMap(X, Y) = New VirtualField(X, Y, Spieler, AIDatabase)
            Next
        Next
        'used later we use this to calculate percentage Influence.
        Dim MaxInfluences As New List(Of Integer)
        Dim MinInfluences As New List(Of Integer)
        For I = 1 To Objektverwalter.Spielfeld.Spieler.Count - 1
            MaxInfluences.Add(0)
            MinInfluences.Add(Integer.MaxValue)
        Next
        'Loop through all Fields
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                'Is here a Unit
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    'Create PFS
                    Dim PFS As New Wegsuchsystem(Unit, , , Wegsuchsystem.SuchartenEinheiten.EigeneEinheitenIgnorieren)
                    'Get Max Days of PFS
                    Dim MaxDays As Integer = PFS.GetMaxDays(Schlachtfeld)
                    'Loop through PFS
                    For Y2 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        For X2 = 0 To Objektverwalter.Spielfeld.Breite - 1
                            'Can we move here
                            If PFS.GetBewegungspunktekostenReal(X2, Y2, Schlachtfeld) >= 0 Then
                                Dim Influence As Integer = (MaxDays - PFS.getDays(X2, Y2, Schlachtfeld))
                                'Set Influence to highest for reachable Terrains at this Turn.
                                VirtualMap(X2, Y2).Influences(Unit.Spieler - 1) += Influence
                                'Save Min or Max Influence when it is bigger than the current one
                            End If
                        Next
                    Next
                    'Calculate Building Influence
                    Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                    If Building IsNot Nothing Then
                        If Building.Spieler > 0 Then
                            If Building.GetRealGebaeudeID <> "VERWEIS" Then
                                Dim L As ObjektLandschaft = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 0, AIDatabase.Building_Influence - 1, Nothing, Objektverwalter.Spielfeld)
                                While L IsNot Nothing
                                    VirtualMap(L.KooX, L.KooY).Influences(Unit.Spieler - 1) += (AIDatabase.Building_Influence - GetDistance(X, Y, L.KooX, L.KooY))
                                    L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 0, AIDatabase.Building_Influence - 1, L, Objektverwalter.Spielfeld)
                                End While
                            End If
                        End If
                    End If
                End If
            Next
        Next
        'get Max Min Influence
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For I = 0 To VirtualMap(X, Y).Influences.Count - 1
                    If VirtualMap(X, Y).Influences(I) > MaxInfluences(I) Then
                        MaxInfluences(I) = VirtualMap(X, Y).Influences(I)
                    End If
                    If MinInfluences(I) > VirtualMap(X, Y).Influences(I) Then
                        MinInfluences(I) = VirtualMap(X, Y).Influences(I)
                    End If
                Next
            Next
        Next

        'Now we have an overall Influence on the Map but we won't to have a percentage instead!
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For I = 0 To VirtualMap(X, Y).Influences.Count - 1
                    If (MaxInfluences(I) - MinInfluences(I)) > 0 Then
                        'This formula calculates a percentage influence depending
                        VirtualMap(X, Y).Influences(I) = (VirtualMap(X, Y).Influences(I) - MinInfluences(I)) / (MaxInfluences(I) - MinInfluences(I))
                    Else
                        VirtualMap(X, Y).Influences(I) = 0
                    End If
                Next
            Next
        Next
        'Now we generate the Frontlines!
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Playerowner As Integer = VirtualMap(X, Y).GetPlayerowner
                'No body owns this Field!
                If Playerowner < 0 Then Continue For
                If Playerowner >= 0 Then
                    Dim L As ObjektLandschaft = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                    While L IsNot Nothing
                        Dim Playerowner2 As Integer = VirtualMap(L.KooX, L.KooY).GetPlayerowner
                        If Playerowner2 >= 0 Then
                            If Playerowner2 <> Playerowner Then
                                If Not VirtualMap(X, Y).FrontField.Contains(Playerowner2) Then
                                    VirtualMap(X, Y).FrontField.Add(Playerowner2)
                                End If
                            End If
                        End If
                        L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                    End While
                End If
            Next
        Next

    End Sub
    ''' <summary>
    ''' Returns the Distance to the Front from this Field for this Unit!
    ''' </summary>
    ''' <param name="PFS"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDistanceToFront(ByVal PFS As Wegsuchsystem, ByVal X As Integer, ByVal Y As Integer) As Integer
        Dim Distance As Integer = Integer.MaxValue
        For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If PFS.GetBewegungspunktekostenReal(X1, Y1, Schlachtfeld) >= 0 Then
                    If VirtualMap(X1, Y1).FrontField.Count > 0 Then
                        If VirtualMap(X1, Y1).FrontField.Contains(Spieler.Spieler - 1) Then
                            Dim Dis As Integer = GetDistancePFS(PFS, X, Y, X1, Y1)
                            If Dis >= 0 Then
                                If Dis < Distance Then Distance = Dis
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Distance
    End Function
    ''' <summary>
    ''' Returns the Distance to the Front without Terrain (Air-Direction)
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Movementpoins"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDistanceToFront(ByVal X As Integer, ByVal Y As Integer, ByVal Movementpoins As Integer)
        Dim Distance As Integer = Integer.MaxValue
        For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If VirtualMap(X1, Y1).FrontField.Count > 0 Then
                    If VirtualMap(X1, Y1).FrontField.Contains(Spieler.Spieler - 1) Then
                        Dim R As Integer = 0
                        Dim Dis As Integer = Math.DivRem(GetDistance(X, Y, X1, Y1), Movementpoins, R)
                        If R <> 0 Then Dis += 1
                        If Dis >= 0 Then
                            If Dis < Distance Then Distance = Dis
                        End If
                    End If
                End If
            Next
        Next
        Return Distance
    End Function
#End Region
#Region "Unit Scoring Classes"
    ''' <summary>
    ''' All our Armies shared in one List!
    ''' </summary>
    ''' <remarks></remarks>
    Private Armies As New List(Of Army)
    ''' <summary>
    ''' The Enemy all Units that go to explode in the next ten Seconds! :)
    ''' </summary>
    ''' <remarks></remarks>
    Private EnemyArmy As Army
    Private Class Army
        Dim AI As AI_Heavy = Nothing
        ''' <summary>
        ''' All our Units with Best Moves for this Turn.
        ''' </summary>
        ''' <remarks></remarks>
        Public Units As New List(Of Unit_Info)

        Public IsEnemyArmy As Boolean = False
        ''' <summary>
        ''' A Unit Info with PFS and best Moves for this Turn.
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Unit_Info
            ''' <summary>
            ''' The Unit we hold the Information
            ''' </summary>
            ''' <remarks></remarks>
            Public Unit As ObjektEinheit
            ''' <summary>
            ''' The Path finding System for this Unit
            ''' </summary>
            ''' <remarks></remarks>
            Public PFS As Wegsuchsystem
            ''' <summary>
            ''' The Targets with the Highest Score and Target Field.
            ''' </summary>
            ''' <remarks></remarks>
            Public Targets As List(Of UnitTarget)
            ''' <summary>
            ''' Here's the Position of this Unit
            ''' </summary>
            ''' <remarks></remarks>
            Public StartField As Point
            Public Sub New(ByVal Unit As ObjektEinheit, ByVal PFS As Wegsuchsystem, ByVal Targets As List(Of UnitTarget))
                Me.Unit = Unit
                Me.PFS = PFS
                Me.Targets = Targets
                StartField = New Point(Unit.X, Unit.Y)
            End Sub

            Public Sub New(ByVal Unit As ObjektEinheit)
                Me.Unit = Unit
                If Unit.HatsichBewegt Then
                    Me.PFS = New Wegsuchsystem(Unit, 0, , Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen, )
                Else
                    Me.PFS = New Wegsuchsystem(Unit, Unit.Bewegungspunkte, , Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen, )
                End If

                StartField = New Point(Unit.X, Unit.Y)
            End Sub
            ''' <summary>
            ''' Returns the Enemy for an Target.
            ''' </summary>
            ''' <param name="Target"></param>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function GetEnemy(ByVal Target As UnitTarget) As ObjektEinheit
                'Get our Enemy depending on Target
                Dim Enemy As ObjektEinheit = Nothing
                If Objektverwalter.Spielfeld.OnMap(Target.Target.X, Target.Target.Y) Then
                    Enemy = Objektverwalter.Spielfeld.Einheiten(Target.Target.X, Target.Target.Y, Unit.GetMap)
                    If Enemy Is Nothing Then
                        Enemy = ObjektLadeklasse.NewEinheit("INF", -1, Target.Target.X, Target.Target.Y)
                    End If
                Else
                    Enemy = ObjektLadeklasse.NewEinheit("INF", -1, Target.Target.X, Target.Target.Y)
                End If
                Return Enemy
            End Function
            ''' <summary>
            ''' Checks if we use this Unit for a First Turn Move?
            ''' </summary>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function FirstTurnMove() As Boolean
                If Not Unit.HatsichBewegt Then
                    If Unit.Leben > 0 Then 'Still Alive?
                        If Targets.Count > 0 Then
                            'Has this Move a Score higher 0?
                            If Targets(0).Score > 0 Then Return True
                        End If
                    End If
                End If
                Return False
            End Function
            ''' <summary>
            ''' Checks if this Unit is still alive or has not moved
            ''' </summary>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function IsAlive() As Boolean
                If Not Unit.HatsichBewegt Then
                    If Unit.Leben > 0 Then 'Still Alive?
                        Return True
                    End If
                End If
                Return False
            End Function
            ''' <summary>
            ''' Loads the Map Unit back.
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub UpdateUnit()
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Me.Unit.X, Me.Unit.Y, Me.Unit.GetMap)
                If Unit IsNot Nothing Then
                    Me.Unit = Unit
                Else
                    Me.Unit.HatsichBewegt = True
                    Me.Unit.Leben = -1
                End If
            End Sub
            ''' <summary>
            ''' Updates this UnitInfo for the next Move
            ''' </summary>
            ''' <param name="UpdatePFS"></param>
            ''' <param name="AI"></param>
            ''' <param name="ThisArmy"></param>
            ''' <remarks></remarks>
            Public Sub UpdateUnitInfo(ByVal UpdatePFS As Boolean, ByVal AI As AI_Heavy, ByVal ThisArmy As AI_Heavy.Army)
                'Create PFS for one turn
                If UpdatePFS Or PFS Is Nothing Then
                    If AI.SecondTurn Then
                        PFS = New Wegsuchsystem(Unit, -1, True, Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen)
                    Else
                        PFS = New Wegsuchsystem(Unit, Unit.Bewegungspunkte, True, Wegsuchsystem.SuchartenEinheiten.EinheitenBeruecksichtigen)
                    End If
                End If
                'Get all Fields that can be crossed this turn
                Dim Fields As List(Of Point) = AI.GetMovableFields(PFS)
                'Select Action with highest Score
                Targets = New List(Of UnitTarget)
                'Loop through all Fields and all Actions and select best one.

                For I3 = 0 To Fields.Count - 1
                    'Get all Actions
                    Dim Actions As List(Of KIModiExtern) = AI.GetActions(Fields(I3), Unit)
                    For I2 = 0 To Actions.Count - 1
                        Dim Score2 As UnitTarget = AI.ScoreActionAtPosition(Unit, Actions(I2), Fields(I3), PFS, ThisArmy, Fields)
                        If Targets.Count > 0 Then
                            If Score2.Score > Targets(0).Score Then
                                Targets.Clear()
                                Targets.Add(Score2)
                            ElseIf Score2.Score = Targets(0).Score Then
                                Targets.Add(Score2)
                            End If
                        Else
                            Targets.Add(Score2)
                        End If
                    Next
                Next
            End Sub
            Private Function AttackOrder(ByVal Targets As List(Of UnitTarget)) As Boolean
                For I = 0 To Targets.Count - 1
                    If Targets(I).Action = KIModiExtern.Angriff Then
                        Return True
                    End If
                Next
                Return False
            End Function
        End Class
        ''' <summary>
        ''' Represents an Action with all Data needed for it.
        ''' </summary>
        ''' <remarks></remarks>
        Public Structure UnitTarget
            ''' <summary>
            ''' The Action the Unit can do here.
            ''' </summary>
            ''' <remarks></remarks>
            Dim Action As KIModiExtern
            ''' <summary>
            ''' From which field
            ''' </summary>
            ''' <remarks></remarks>
            Dim Field As Point
            ''' <summary>
            ''' Some Actions need to have a target for example an attack.
            ''' </summary>
            ''' <remarks></remarks>
            Dim Target As Point
            ''' <summary>
            ''' The Score we've calculated for this Action.
            ''' </summary>
            ''' <remarks></remarks>
            Dim Score As Double
            Public Sub New(ByVal Score As Integer)
                Action = KIModiExtern.Warten
                Field = New Point(-1, 1)
                Target = New Point(-1, -1)
                Me.Score = Score
            End Sub
            Public Sub New(ByVal Score As Integer, ByVal Action As KIModiExtern)
                Me.Action = Action
                Field = New Point(-1, 1)
                Target = New Point(-1, -1)
                Me.Score = Score
            End Sub
            Public Sub New(ByVal Score As Integer, ByVal Action As KIModiExtern, ByVal Field As Point)
                Me.Action = Action
                Me.Field = Field
                Target = New Point(-1, -1)
                Me.Score = Score
            End Sub
        End Structure
        ''' <summary>
        ''' Creates the Army of all Units for a First Turn Move
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New(ByVal ArmyUnits As ObjektEinheit(), ByVal AI As AI_Heavy)
            Me.AI = AI
            'Clear old Infos
            Units.Clear()
            For I = 0 To ArmyUnits.Length - 1
                Units.Add(New Unit_Info(ArmyUnits(I)))
            Next

            'loop through all Units
            For I = 0 To ArmyUnits.Length - 1
                'Has Unit moved?
                If Not ArmyUnits(I).HatsichBewegt Then
                    If ArmyUnits(I).Leben > 0 Then 'Still Alive?
                        Units(I).UpdateUnitInfo(False, AI, Me)
                    End If
                End If
            Next

        End Sub
        ''' <summary>
        ''' Creates the Army of all Units for a First Turn Move
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New(ByVal ArmyUnits As List(Of ObjektEinheit), ByVal AI As AI_Heavy)
            Me.AI = AI
            'Clear old Infos
            Units.Clear()
            For I = 0 To ArmyUnits.Count - 1
                Units.Add(New Unit_Info(ArmyUnits(I)))
            Next
            'loop through all Units
            For I = 0 To ArmyUnits.Count - 1
                'Has Unit moved?
                If Not ArmyUnits(I).HatsichBewegt Then
                    If ArmyUnits(I).Leben > 0 Then 'Still Alive?
                        Units(I).UpdateUnitInfo(False, AI, Me)
                    End If
                End If
            Next
        End Sub
        ''' <summary>
        ''' Creates an Army existing out of all Enemy Units in Order to increase Gamespeed!
        ''' </summary>
        ''' <param name="Enemies"></param>
        ''' <param name="AI"></param>
        ''' <param name="EnemyArmy"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal Enemies As List(Of ObjektEinheit), ByVal AI As AI_Heavy, ByVal EnemyArmy As Boolean)
            Me.AI = AI
            Units.Clear()
            For I = 0 To Enemies.Count - 1
                Units.Add(New Unit_Info(Enemies(I)))
            Next
            Me.IsEnemyArmy = EnemyArmy
        End Sub
        ''' <summary>
        ''' We're going to update all fields, we've changed.
        ''' </summary>
        ''' <param name="Start"></param>
        ''' <param name="Target"></param>
        ''' <param name="Enemy"></param>
        ''' <remarks></remarks>
        Public Sub UpdateUnits(ByVal Start As Point, ByVal Target As Point, ByVal Enemy As Point, ByVal Range As Integer, ByRef VirtualMap As VirtualField(,), ByVal Player As ObjektSpieler, ByVal AIDatabase As Database)
            Dim UpdateUnits As New List(Of Integer)
            Dim UpdateFields As New List(Of Point)
            Dim I As Integer = 0
            While I < Units.Count
                If Units(I).Unit.Leben > 0 Then
                    I += 1
                Else
                    Units.RemoveAt(I)
                End If
            End While
            For I = 0 To Units.Count - 1
                Units(I).UpdateUnit()
                If Units(I).IsAlive Or (IsEnemyArmy) Then

                    Dim Added As Boolean = False
                    Dim L As ObjektLandschaft = Nothing

                    If (Start.X <> Target.X Or Start.Y <> Target.Y) Then
                        'Go through all 4 Neighbours and check if this Unit can move over it!
                        L = Wegsuchsystem.getFeldRundrum(Start.X, Start.Y, Schlachtfeld, 0, 1, L, Objektverwalter.Spielfeld)
                        While L IsNot Nothing
                            If Objektverwalter.Spielfeld.OnMap(L.KooX, L.KooY) Then
                                UpdateFields.Add(New Point(L.KooX, L.KooY))
                                If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                    If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) <= Units(I).Unit.Bewegungspunkte Then
                                        'We could move near this Startfield. Update it!
                                        UpdateUnits.Add(I)
                                        Added = True
                                        Exit While
                                    End If
                                End If
                            End If
                            L = Wegsuchsystem.getFeldRundrum(Start.X, Start.Y, Schlachtfeld, 0, 1, L, Objektverwalter.Spielfeld)
                        End While

                        If Target.X >= 0 And Target.Y >= 0 And Not Added Then
                            L = Nothing
                            L = Wegsuchsystem.getFeldRundrum(Target.X, Target.Y, Schlachtfeld, 0, Range, L, Objektverwalter.Spielfeld)
                            While L IsNot Nothing
                                If Objektverwalter.Spielfeld.OnMap(L.KooX, L.KooY) Then
                                    UpdateFields.Add(New Point(L.KooX, L.KooY))
                                    If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                        If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) <= Units(I).Unit.Bewegungspunkte Then

                                            'We could move near this Targetfield. Update it!
                                            UpdateUnits.Add(I)
                                            Added = True
                                            Exit While
                                        End If
                                    End If
                                End If
                                L = Wegsuchsystem.getFeldRundrum(Start.X, Start.Y, Schlachtfeld, 0, Range, L, Objektverwalter.Spielfeld)
                            End While
                        End If
                    End If

                    If Enemy.X >= 0 And Enemy.Y >= 0 And Not Added Then
                        L = Nothing
                        L = Wegsuchsystem.getFeldRundrum(Enemy.X, Enemy.Y, Schlachtfeld, 1, Range, L, Objektverwalter.Spielfeld)
                        While L IsNot Nothing
                            If Objektverwalter.Spielfeld.OnMap(L.KooX, L.KooY) Then
                                UpdateFields.Add(New Point(L.KooX, L.KooY))
                                If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                    If Units(I).PFS.GetBewegungspunktekostenReal(L.KooX, L.KooY, Schlachtfeld) <= Units(I).Unit.Bewegungspunkte Then

                                        'We could move near this Startfield. Update it!
                                        UpdateUnits.Add(I)
                                        Added = True
                                        Exit While
                                    End If
                                End If
                            End If
                            L = Wegsuchsystem.getFeldRundrum(Start.X, Start.Y, Schlachtfeld, 1, Range, L, Objektverwalter.Spielfeld)
                        End While
                    End If
                    If Not Added Then 'No Update yet?
                        'Is the Enemy on the Map?
                        If Objektverwalter.Spielfeld.OnMap(Enemy) Then
                            If Units(I).Targets IsNot Nothing Then
                                'Loop through all Targets
                                For I2 = 0 To Units(I).Targets.Count - 1
                                    If Units(I).Targets(I2).Target = Enemy Then
                                        'This Enemy was an Target of our Unit. Update!!!
                                        UpdateUnits.Add(I)
                                        Added = True
                                        Exit For
                                    End If
                                Next
                            End If
                        End If
                    End If
                    If Not Added Then
                        If Units(I).Targets IsNot Nothing Then
                            For I2 = 0 To Units(I).Targets.Count - 1
                                Select Case Units(I).Targets(I2).Action
                                    Case KIModiExtern.Explosion
                                        UpdateUnits.Add(I)
                                        Added = True
                                        Exit For
                                    Case KIModiExtern.SiloZuenden
                                        UpdateUnits.Add(I)
                                        Added = True
                                        Exit For
                                End Select
                            Next
                        End If
                    End If
                End If
            Next
            'Update all Unit moves we've found.
            For I = 0 To UpdateUnits.Count - 1
                If IsEnemyArmy Then
                    Units(UpdateUnits(I)) = New Unit_Info(Units(UpdateUnits(I)).Unit)
                Else
                    Units(UpdateUnits(I)).UpdateUnitInfo(True, AI, Me)
                End If
            Next
            For I = 0 To UpdateFields.Count - 1
                VirtualMap(UpdateFields(I).X, UpdateFields(I).Y).UpdateField(Player, AIDatabase)
            Next
        End Sub
    End Class
#End Region
    ''' <summary>
    ''' Database for this AI.
    ''' </summary>
    ''' <remarks></remarks>
    Public AIDatabase As Database
#Region "Initialize AI"
    ''' <summary>
    ''' Creates a new AI Object
    ''' </summary>
    ''' <param name="Player"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Player As ObjektSpieler)
        'Initial Main AI, as we won't use Basic Values from earlier AI's we set them to unused.
        MyBase.New(Player, -1, -1, -1, Besetzungsprioritaeten.Keine, GeldTPAngriffsModus.Beides, -1, 1 / 3, 4, 1 / 3)
        'Do we have a Database for this AI?
        If AIDatabase Is Nothing Then
            AIDatabase = New Database(Spieler, Me)
        End If
    End Sub
    ''' <summary>
    ''' Starts the AI and Inis the AI Threat
    ''' </summary>
    ''' <remarks></remarks>
    Public Overrides Sub LaunchAI()
        MyBase.LaunchAI()
    End Sub
    ''' <summary>
    ''' Inis some Sub Fields and Functions for the AI
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Ini_AI_Map()
        If AIDatabase Is Nothing Then
            AIDatabase = New Database(Spieler, Me)
        End If
        CreateVirtualMap()
        Armies.Clear()
        GetAllBuildings()
    End Sub
    ''' <summary>
    ''' Inis the AI Strategy for each Player
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Ini_AI_Strategy()
        Dim Own_Units As Integer = Spieler.CountUnits
        Dim Player_Strength As Integer = Spieler.CalculateSpielerStaerke
        'Our Strength!!!
        For I = 1 To Objektverwalter.Spielfeld.Spieler.Length - 1
            'Create the AI Strategy for this Player.
            If I <> Spieler.Spieler Then
                Dim Enemy_Units As Integer = Objektverwalter.Spielfeld.Spieler(I).CountUnits
                Dim Enemy_Strength As Integer = Objektverwalter.Spielfeld.Spieler(I).CalculateSpielerStaerke
                'Than both Players are equal strong 
                Dim Compared_Balanced_Strength As Integer = 0
                If Enemy_Units <> 0 Then
                    Compared_Balanced_Strength += Own_Units / Enemy_Units
                End If
                If Enemy_Strength <> 0 Then
                    Compared_Balanced_Strength += Player_Strength / Enemy_Strength
                End If
                If Objektverwalter.Spielfeld.Spieler(I).Einkommen <> 0 Then
                    Compared_Balanced_Strength += Spieler.Einkommen / Objektverwalter.Spielfeld.Spieler(I).Einkommen
                End If
                Dim Compared_Strength As Integer = Compared_Balanced_Strength
                Compared_Balanced_Strength *= AIDatabase.PlayerDatas(I - 1).PlayerPriority
                If Objektverwalter.Spielfeld.Spieler.Length - 2 <> 0 Then
                    Compared_Balanced_Strength /= Objektverwalter.Spielfeld.Spieler.Length - 2
                End If
                Select Case Compared_Balanced_Strength
                    'We're a lot stronger Assualt
                    Case Is > 2.25#
                        If Compared_Strength > 5 Then
                            AIDatabase.PlayerDatas(I - 1).AI_Strategy.LoadStrategy(Database.PlayerData.Player_AI_Strategy.Strategy.Offensive)
                        Else
                            AIDatabase.PlayerDatas(I - 1).AI_Strategy.LoadStrategy(Database.PlayerData.Player_AI_Strategy.Strategy.Deffensive)
                        End If
                        'We're weaker or a little bit stronger (Deffensive)
                    Case Is <= 1.8#
                        AIDatabase.PlayerDatas(I - 1).AI_Strategy.LoadStrategy(Database.PlayerData.Player_AI_Strategy.Strategy.Deffensive)
                        'We're strong enough to react a little more Aggresiv
                    Case Else
                        If Compared_Strength > 4 Then
                            AIDatabase.PlayerDatas(I - 1).AI_Strategy.LoadStrategy(Database.PlayerData.Player_AI_Strategy.Strategy.Standard)
                        Else
                            AIDatabase.PlayerDatas(I - 1).AI_Strategy.LoadStrategy(Database.PlayerData.Player_AI_Strategy.Strategy.Deffensive)
                        End If
                End Select
            End If
        Next
    End Sub
    ''' <summary>
    ''' Does a Front change to the Air Battle
    ''' </summary>
    ''' <param name="Sortieren"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub Schlachtwechsel(ByVal Sortieren As ObjektKI.EinheitenSortierKriterien)
        While BackbufferSpiel.GetBufferLength > 0 And Objektverwalter.Spielfeld.Animationen.Length > 0
            Threading.Thread.Sleep(ThreadSleepTime)
        End While

        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then
            'Sorgt fuer einen Schlachtwechsel der KI.
            If Schlachtfeld = ObjektSpielfeld.Bodenschlacht Then
                Schlachtfeld = ObjektSpielfeld.Luftschlacht
            Else
                Schlachtfeld = ObjektSpielfeld.Bodenschlacht
            End If
            newUnitsArrived = True
        End If

        Objektverwalter.Spielfeld.SchlachtWechseln()


    End Sub
#End Region
    ''' <summary>
    ''' This is the Main Loop of this AI
    ''' </summary>
    ''' <remarks></remarks>
    Public Overrides Sub KISchleife()
        Objektverwalter.Spielfeld.EingabenErlauben = False
        Schleife = False
        KIModusIntern = KIModiIntern.KIStart
        'Start some pre AI functions!
        SecondTurn = False

        Ini_AI_Strategy()
        newUnitsArrived = True

        KIModusIntern = KIModiIntern.KIStart
        If UseCOPower(False) Then KIWarten(8)
        Building_Fire()


        'This let us loop while we want to do Actions
        While (Not Schleife)
            KIModusIntern += 1

            If newUnitsArrived Then

                Ini_AI_Map()
                'Create Enemy Army!
                Dim Enemies As New List(Of ObjektEinheit)
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        Dim Enemy As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                        If Enemy IsNot Nothing Then
                            If Enemy.GetSpieler.Team <> Spieler.Team Then
                                Enemies.Add(Enemy)
                            End If
                        End If
                    Next
                Next
                EnemyArmy = New Army(Enemies, Me, True)
                'Create all Units
                Armies.Clear()
                Armies.Add(New Army(GetUnits, Me))
                newUnitsArrived = False
            End If
            For I2 = 0 To Armies.Count - 1
                FirstTurnMove(Armies(I2))
            Next
            'Only for Testing
            GetAllUnits(EinheitenSortierKriterien.GroessterBewegungsradius)
            SecondTurnMove()

            'Produce Units
            BuildUnits()
            If newUnitsArrived Then
                'Go to Start
            Else
                KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen
                If UseCOPower(False) Then
                    KIWarten(8)
                    KIModusIntern = KIModiIntern.StartWarten
                    newUnitsArrived = True
                Else
                    Schleife = True
                End If
            End If


        End While

    End Sub
    Enum FirstTurnPriority
        Capture
        Indirects
        Directs
        Infantries
        Wait_Indirects
        Wait_Directs
        Wait_Infantries
        None
    End Enum
    ''' <summary>
    ''' Identifies the current priorised Unit Attacks
    ''' </summary>
    ''' <remarks></remarks>
    Dim TurnPriority As FirstTurnPriority = FirstTurnPriority.Capture
    ''' <summary>
    ''' Here we do Actions during our Move
    ''' </summary>
    ''' <param name="Troops"></param>
    ''' <remarks></remarks>
    Private Sub FirstTurnMove(ByVal Troops As Army)
        Dim MovedUnit As Boolean = True
        SecondTurn = False
        TurnPriority = FirstTurnPriority.Capture
        'Loop while we moved a Unit last loop
        While MovedUnit
            'Check Power Use!
            If UseCOPower(True) Then KIWarten(8)
            'Fire with Buildings?
            Building_Fire()
            'No Unit was moved
            MovedUnit = False

            'Go to all Units
            Dim BestMoveUnits As New List(Of Army.Unit_Info)
            'This Value tries to balance some Inbalance Output of the Score calculation in Order to fire on Units in an certain Order
            Dim BestMoveMultiplikator As Single = 1
            Dim Scored As Boolean = False
            'Find best move out of all Units.
            For I = 0 To Troops.Units.Count - 1
                If Troops.Units(I).FirstTurnMove Then
                    Dim ScoreMultiplikator As Single = 1
                    'Capturing?
                    If Troops.Units(I).Targets(0).Action = KIModiExtern.Besetzen Then
                        Scored = True
                        'Is the Order an Attack?
                    ElseIf Troops.Units(I).Targets(0).Action = KIModiExtern.Angriff Then
                        Select Case TurnPriority
                            Case FirstTurnPriority.Indirects
                                If GetDistance(Troops.Units(I).Targets(0).Field, Troops.Units(I).Targets(0).Target) > 1 Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case FirstTurnPriority.Directs
                                If GetDistance(Troops.Units(I).Targets(0).Field, Troops.Units(I).Targets(0).Target) = 1 And Troops.Units(I).Unit.KannBesetzen = False Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case FirstTurnPriority.Infantries
                                If GetDistance(Troops.Units(I).Targets(0).Field, Troops.Units(I).Targets(0).Target) = 1 And Troops.Units(I).Unit.KannBesetzen = True Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case Else
                                Scored = True
                                'Do Nothing
                        End Select
                    ElseIf Troops.Units(I).Targets(0).Action = KIModiExtern.Warten Then 'Extra Scorepoints for waiting...
                        Select Case TurnPriority
                            Case FirstTurnPriority.Wait_Indirects
                                If Troops.Units(I).Unit.MaximaleReichweite > 1 Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case FirstTurnPriority.Wait_Directs
                                If Troops.Units(I).Unit.IsDirectUnit And Troops.Units(I).Unit.KannBesetzen = False Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case FirstTurnPriority.Wait_Infantries
                                If Troops.Units(I).Unit.IsDirectUnit And Troops.Units(I).Unit.KannBesetzen = True Then
                                    ScoreMultiplikator = AIDatabase.TurnPriority
                                    Scored = True
                                End If
                            Case Else
                                Scored = True
                                'Do Nothing
                        End Select
                    ElseIf TurnPriority = FirstTurnPriority.None Then
                        Scored = True
                    End If
                    'Waiting won't be used during attacks.
                    If Troops.Units(I).Targets(0).Action <> KIModiExtern.Warten And TurnPriority < FirstTurnPriority.Wait_Indirects Then
                        If BestMoveUnits.Count > 0 Then
                            If BestMoveUnits(0).Targets(0).Score * BestMoveMultiplikator < Troops.Units(I).Targets(0).Score * ScoreMultiplikator Then
                                'This Unit can do a better move update it.
                                BestMoveUnits.Clear()
                                BestMoveUnits.Add(Troops.Units(I))
                                BestMoveMultiplikator = ScoreMultiplikator
                            ElseIf BestMoveUnits(0).Targets(0).Score * BestMoveMultiplikator = Troops.Units(I).Targets(0).Score * ScoreMultiplikator Then
                                If BestMoveUnits(0).Targets.Count > Troops.Units(I).Targets.Count Then
                                    'This Unit has less best clear Array and use this for our next move
                                    BestMoveUnits.Clear()
                                    BestMoveUnits.Add(Troops.Units(I))
                                    BestMoveMultiplikator = ScoreMultiplikator
                                ElseIf BestMoveUnits(0).Targets.Count = Troops.Units(I).Targets.Count Then
                                    'As good as the current Unit add it for random selection.
                                    BestMoveUnits.Add(Troops.Units(I))
                                    If BestMoveMultiplikator < ScoreMultiplikator Then BestMoveMultiplikator = ScoreMultiplikator
                                End If
                            End If
                        Else
                            BestMoveUnits.Add(Troops.Units(I))
                            BestMoveMultiplikator = ScoreMultiplikator
                        End If
                    End If
                End If
            Next
            If Not Scored Then
                TurnPriority += 1
                If TurnPriority > FirstTurnPriority.None Then
                    TurnPriority = FirstTurnPriority.None
                Else
                    MovedUnit = True
                End If
                Continue While
            End If
            If BestMoveUnits.Count > 0 Then
                'Reset Priorities
                TurnPriority = FirstTurnPriority.Indirects
                'Select a random Unit out of the best Units
                Dim Unit As Army.Unit_Info = BestMoveUnits(Zufallszahl(0, BestMoveUnits.Count - 1))
                'Select a Random Move out of the Best Moves
                Dim Target As Army.UnitTarget = Unit.Targets(Zufallszahl(0, Unit.Targets.Count - 1))
                Dim EnemyPosition As Point = Target.Target
                'It may happen that just waiting gets an higher Score than Capturing we fix that here!
                If Target.Action = KIModiExtern.Warten Then
                    If CanCapture(Target.Target.X, Target.Target.Y, Unit.Unit) Then
                        Target.Action = KIModiExtern.Besetzen
                    End If
                End If
                'Do this Action on Enemy sometimes Enemy is a Dummy
                Einheitauswaehlen(Unit.Unit, Target.Field, Target.Action, Unit.GetEnemy(Target), Unit.PFS, 4)
                Dim Range As Integer = 1
                Select Case Target.Action
                    Case KIModiExtern.Explosion
                        Unit.Unit.Leben = -1
                        Range = 3
                    Case KIModiExtern.SiloZuenden
                        Range = Objektverwalter.Spielfeld.Landschaften(Target.Field.X, Target.Field.Y, Schlachtfeld).Gebaeude.Reichweite
                End Select

                'Update the Unit Array for the next move.
                Troops.UpdateUnits(Unit.StartField, Target.Field, EnemyPosition, Range, VirtualMap, Spieler, AIDatabase)
                EnemyArmy.UpdateUnits(Unit.StartField, Target.Field, EnemyPosition, Range, VirtualMap, Spieler, AIDatabase)
                'We have moved a Unit
                MovedUnit = True
            End If
        End While
    End Sub
    ''' <summary>
    ''' Here we only wait! We try to look in the future etc.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub SecondTurnMove()
        SecondTurn = True
        'Testing
        MomentaneEinheit = 0
        NahkampfZiehen()
        MomentaneEinheit = 0
        InfanterieZiehen()
        MomentaneEinheit = 0
        Fernkampfziehen()
        MomentaneEinheit = 0
        TruppenWegZiehen()
        MomentaneEinheit = 0
    End Sub
    Protected Overrides Function CalculateRealZiel(ByRef WSS As Wegsuchsystem, ByVal Ziel As System.Drawing.Point, ByVal Einheit As ObjektEinheit, ByRef Opfer As System.Drawing.Point) As System.Drawing.Point
        Return Ziel
    End Function
#Region "Imported for Test"
    ''' <summary>
    ''' So werden die Einheiten  von einfachen KI's zum Ziel gefuehrt
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub NahkampfZiehen()
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheiten(MomentaneEinheit).MinimaleReichweite = 1 Or Not Einheiten(MomentaneEinheit).Waffe1 = "Keine" Then
                        If Einheiten(MomentaneEinheit).KannBesetzen = False Then
                            'So das ist vieleicht eine Nahkampfeinheit und zwar kein Infaterist
                            'und diese Einheit kann nicht Angreifen oder doch nah ja das ist ja eine doofe KI
                            'Also keine Abfrage!
                            Dim WSS As New Wegsuchsystem(Einheiten(MomentaneEinheit), Einheiten(MomentaneEinheit).X, Einheiten(MomentaneEinheit).Y, Einheiten(MomentaneEinheit).GetMap, -1)
                            Dim Ziel As Point = GetNaehestenNahkampfFeind(Einheiten(MomentaneEinheit), WSS)
                            If Ziel.X >= 0 Then
                                Einheitauswaehlen(Einheiten(MomentaneEinheit), Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                            Else
                                Ziel = ZumNaehestenHQZiehen(Einheiten(MomentaneEinheit), WSS)
                                If Ziel.X > 0 Then
                                    Einheitauswaehlen(Einheiten(MomentaneEinheit), Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        KIModusIntern = KIModiIntern.Infanterieziehen
    End Sub
    ''' <summary>
    ''' So ziehen die Infanteristen
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub InfanterieZiehen()
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheiten(MomentaneEinheit).KannBesetzen Then
                        If Not Einheiten(MomentaneEinheit).Waffe1 = "Keine" Or Einheiten(MomentaneEinheit).MinimaleReichweite = 1 Then
                            Dim WSS As Wegsuchsystem = Nothing
                            Dim Ziel As Point2 = GetBestesNahkampfOpfer(Einheiten(MomentaneEinheit), WSS)
                            If Ziel.Point1.X >= 0 And Ziel.Point2.X >= 0 Then
                                Einheitauswaehlen(Einheiten(MomentaneEinheit), Ziel.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Ziel.Point2.X, Ziel.Point2.Y, Schlachtfeld), WSS, 4)
                            Else
                                'wir schauen ob wir zu einer Besetzung gehen

                                If InfantrieMoveToTransporterOrBesetzung(Einheiten(MomentaneEinheit)) Then
                                    Continue While
                                Else
                                    WSS = New Wegsuchsystem(Einheiten(MomentaneEinheit), , True)
                                    'Wir gehen zu einem Feind.
                                    Dim Zielpunkt As Point = GetNaehestenNahkampfFeind(Einheiten(MomentaneEinheit), WSS)
                                    If Zielpunkt.X >= 0 Then
                                        Einheitauswaehlen(Einheiten(MomentaneEinheit), Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                                    Else
                                        Dim Z As Point = ZumNaehestenHQZiehen(Einheiten(MomentaneEinheit), WSS)
                                        If Z.X > 0 Then
                                            Einheitauswaehlen(Einheiten(MomentaneEinheit), Z, KIModiExtern.Warten, Nothing, WSS, 4)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        KIModusIntern = KIModiIntern.Fernkampfziehen
    End Sub
    ''' <summary>
    ''' So werden die Fernkampf Einheiten der Kinderleichten KI gezogen
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Fernkampfziehen()
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheiten(MomentaneEinheit).MaximaleReichweite > 1 Then
                        Dim WSS As New Wegsuchsystem(Einheiten(MomentaneEinheit), Einheiten(MomentaneEinheit).X, Einheiten(MomentaneEinheit).Y, Einheiten(MomentaneEinheit).GetMap, -1)
                        Dim Ziel As Point = GetNaehestesFernkampffeld(Einheiten(MomentaneEinheit), WSS)
                        If Ziel.X >= 0 Then
                            Einheitauswaehlen(Einheiten(MomentaneEinheit), Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                        Else
                            Ziel = ZumNaehestenHQZiehen(Einheiten(MomentaneEinheit), WSS)
                            If Ziel.X > 0 Then
                                Einheitauswaehlen(Einheiten(MomentaneEinheit), Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        KIModusIntern = KIModiIntern.TransporterVerladen
    End Sub
#End Region
#Region "Building Fire"
    ''' <summary>
    ''' Intelligen Deffence System developed by Robosturm for Intelligent Base Deffence.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub Building_Fire()
        MomentaneEinheit = 0
        While MomentaneEinheit < Gebaeude.Length
            Dim MomGebaeude As ObjektGebaeude = Gebaeude(MomentaneEinheit)
            If Not MomGebaeude.GetRealGebaeudeID = "VERWEIS" Then
                If MomGebaeude.Feuerbereit = 0 Then
                    If TypeOf MomGebaeude Is GebaeudeLaser Then
                        If FireLaser(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeAruura Then
                        If FireAzuura(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeOmega_Rakete Then
                        Dim Omega As GebaeudeOmega_Rakete = MomGebaeude
                        If Omega.RaketeFeuerbereit = True Then
                            Dim Ziel As Point = GetBestenEinschlagsOrt(Omega.Reichweite, Omega.Schaden)
                            If Ziel.X >= 0 Then
                                GebaeudeAuswaehlen(KIModiExtern.OmegaRaketeStarten, Omega, New EinheitArtillerie(0, Ziel.X, Ziel.Y), 4)
                            End If
                        ElseIf Spieler.Fonds > 30000 Then
                            For I = 0 To Omega.Variablen.Length - 1
                                If Omega.Variablen(I).Wert = 1 Then
                                    'Wir bauen einen Teil der Omega-Rakete
                                    GebaeudeAuswaehlen(KIModiExtern.OmegaUpgradeKaufen, Omega, New EinheitArtillerie(0, I, 0), 4)
                                    Exit For
                                End If
                            Next
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeMonolith Then
                        If FireCrystallMonolith(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeKristall Then
                        If FireCrystallMonolith(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_N Then
                        If FireDeathRayNorth(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_W Then
                        If FireDeathRayWest(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_S Then
                        If FireDeathRaySouth(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_O Then
                        If FireDeathRayEast(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    Else 'A Minicanon or something like this!
                        Dim Ziel As Point = GetBestesGebaeudeFeuer(MomGebaeude)
                        If Ziel.X >= 0 And Ziel.Y >= 0 Then
                            If MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussN Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussW Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussS Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussO Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld), 4)
                            Else
                                'Wir muessen erst noch eine virtuelle Einheit erschaffen.=)
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, Ziel.X, Ziel.Y, False), 4)
                            End If
                        End If
                    End If
                ElseIf TypeOf MomGebaeude Is GebaeudeFabrik Then
                    FactoryBuild(MomGebaeude)
                End If
            End If
            MomentaneEinheit += 1
        End While
        MomentaneEinheit = 0
    End Sub
    ''' <summary>
    ''' should we use our new Laser system?
    ''' </summary>
    ''' <param name="Laser"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function FireLaser(ByVal Laser As GebaeudeLaser) As Boolean
        Dim FondsDamage As Integer = 0
        For I As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X - I
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then

                    Dim Damage As Integer = E.Leben - Laser.Schaden
                    If Damage >= 1 Then
                        Damage = Laser.Schaden
                    Else
                        Damage = Laser.Schaden + Damage - 1
                    End If

                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach links markieren
        For I2 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X + I2
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    Dim Damage As Integer = E.Leben - Laser.Schaden
                    If Damage >= 1 Then
                        Damage = Laser.Schaden
                    Else
                        Damage = Laser.Schaden + Damage - 1
                    End If
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach oben markieren
        For I3 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y - I3
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    Dim Damage As Integer = E.Leben - Laser.Schaden
                    If Damage >= 1 Then
                        Damage = Laser.Schaden
                    Else
                        Damage = Laser.Schaden + Damage - 1
                    End If
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach unten markiern
        For I4 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y + I4
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    Dim Damage As Integer = E.Leben - Laser.Schaden
                    If Damage >= 1 Then
                        Damage = Laser.Schaden
                    Else
                        Damage = Laser.Schaden + Damage - 1
                    End If
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * (Damage / 10) * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        If FondsDamage > 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Oh yeah! Let's use a Monolith or Crystall right now?
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function FireCrystallMonolith(ByVal Gebaeude As ObjektGebaeude) As Boolean
        Dim Kreis(,) As Integer = Kreisfunktion(Gebaeude.Reichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                If Kreis(X, Y) > 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Gebaeude.Rechteck.X - Gebaeude.Reichweite + X, Gebaeude.Rechteck.Y - Gebaeude.Reichweite + Y, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.Spieler = Gebaeude.Spieler Then
                            If E.Munition < E.MunitionMax Or E.Treibstoff < E.SpritMax Then
                                Return True
                            ElseIf E.getKP < 8 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Oh yeah! Let's use a Monolith or Crystall right now?
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function FireAzuura(ByVal Gebaeude As ObjektGebaeude) As Boolean
        Dim Kreis(,) As Integer = Kreisfunktion(Gebaeude.Reichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                If Kreis(X, Y) > 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Gebaeude.Rechteck.X - Gebaeude.Reichweite + X, Gebaeude.Rechteck.Y - Gebaeude.Reichweite + Y, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Gebaeude.GetSpieler.Team Then
                            Return True
                        End If
                    End If
                End If
            Next
        Next
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function FireDeathRayNorth(ByVal DeathRay As GebaeudeSchocklaser_N, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For Y = -DeathRay.Reichweite To -2
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        Dim DoneDamage As Integer = E.Leben - DeathRay.Schaden
                        If DoneDamage >= 1 Then
                            DoneDamage = DeathRay.Schaden
                        Else
                            DoneDamage = DeathRay.Schaden + Damage - 1
                        End If
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten + (DoneDamage / 10) * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function FireDeathRayWest(ByVal DeathRay As GebaeudeSchocklaser_W, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For X = -DeathRay.Reichweite To -2
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        Dim DoneDamage As Integer = E.Leben - DeathRay.Schaden
                        If DoneDamage >= 1 Then
                            DoneDamage = DeathRay.Schaden
                        Else
                            DoneDamage = DeathRay.Schaden + Damage - 1
                        End If
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * (DoneDamage / 10) * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function FireDeathRayEast(ByVal DeathRay As GebaeudeSchocklaser_O, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For X = 2 To DeathRay.Reichweite
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        Dim DoneDamage As Integer = E.Leben - DeathRay.Schaden
                        If DoneDamage >= 1 Then
                            DoneDamage = DeathRay.Schaden
                        Else
                            DoneDamage = DeathRay.Schaden + Damage - 1
                        End If
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * (DoneDamage / 10) * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function FireDeathRaySouth(ByVal DeathRay As GebaeudeSchocklaser_S, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For Y = 2 To DeathRay.Reichweite
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        Dim DoneDamage As Integer = E.Leben - DeathRay.Schaden
                        If DoneDamage >= 1 Then
                            DoneDamage = DeathRay.Schaden
                        Else
                            DoneDamage = DeathRay.Schaden + Damage - 1
                        End If
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * (DoneDamage / 10) * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Produces Units with a Factory!
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub FactoryBuild(ByVal Factory As GebaeudeFabrik)
        Dim Build As Boolean = True
        Dim AverageSpendFonds As Integer = Factory.Variablen(1).Wert
        Dim Doors As Integer = 1
        If Factory.Variablen(0).Wert = 7 Then
            Doors = 3
            AverageSpendFonds /= Doors
        ElseIf Factory.Variablen(0).Wert > 2 And Factory.Variablen(0).Wert <> 4 Then
            Doors = 2
            AverageSpendFonds /= Doors
        End If
        Dim ExtraFonds As Integer = Factory.Variablen(1).Wert - AverageSpendFonds * Doors
        'Not Attackable Units or Units we do very less Damage but need to be destroyed
        Dim UndestroyableUnits As New List(Of ObjektEinheit)
        'Get all our Units
        Dim OurUnits As List(Of ObjektEinheit) = GetUnits()
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    'Enemy Unit?
                    If Unit.GetSpieler.Team <> Spieler.Team Then
                        'Loop through our Units.
                        For I = 0 To OurUnits.Count - 1
                            Dim Dmg As Single = GetDamage(OurUnits(I), Unit)
                            Dim CDmg As Single = GetDamage(Unit, OurUnits(I))
                            'Either the CDmg is very low and the Dmg at least greater 10 or our Damage is very big!
                            If Not Undestroyable(Dmg, CDmg, Unit.Leben) Then
                                Exit For
                            ElseIf I = OurUnits.Count - 1 Then
                                UndestroyableUnits.Add(Unit)
                            End If
                        Next
                    End If
                End If
            Next
        Next

        Dim PFS1 As New List(Of Wegsuchsystem)
        Dim PFS2 As New List(Of Wegsuchsystem)
        Dim PFS3 As New List(Of Wegsuchsystem)

        Dim Enemys As List(Of ObjektEinheit) = GetEnemyUnits()

        While Factory.Variablen(1).Wert > 0 And Build
            Build = False
            Dim DirectsToIndirects As Single = CalculateDirectsToIndirects()
            Dim Door As Integer = Factory.Variablen(0).Wert
            'Buildings
            Dim BuildUnits As New List(Of ObjektEinheit)
            Dim Score As Single = Single.MinValue
            'Finding the next production Door
            If Door >= 4 Then
                Dim Units As String() = Factory.GetBauEinheiten(Factory.Rechteck.X + 1, Factory.Rechteck.Y + 2)
                For Each ID In Units
                    Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(ID, Spieler.Spieler, Factory.Rechteck.X + 1, Factory.Rechteck.Y + 2, False)
                    Dim PFS As Wegsuchsystem = Nothing
                    For I = 0 To PFS3.Count - 1
                        If PFS3(I).Einheit.EinheitenID = ID Then
                            PFS = PFS3(I)
                            Exit For
                        End If
                    Next
                    If PFS Is Nothing Then
                        PFS = New Wegsuchsystem(Unit, Unit.X, Unit.Y, Schlachtfeld, -1, True, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren, True)
                        PFS3.Add(PFS)
                    End If
                    Dim Score2 As Single = ScoreUnitBuild(Unit, PFS, UndestroyableUnits, Enemys, AverageSpendFonds, ExtraFonds, DirectsToIndirects)
                    If BuildUnits.Count > 0 Then
                        'Save best Unit(s)
                        If Score2 < Score + WIDE And Score2 > Score - WIDE Then
                            BuildUnits.Add(Unit)
                            If Score2 > Score Then Score = Score2
                        ElseIf Score2 > Score Then
                            Score = Score2
                            BuildUnits.Clear()
                            BuildUnits.Add(Unit)
                        End If
                    Else
                        Score = Score2
                        BuildUnits.Add(Unit)
                    End If
                Next
                Door -= 4
            End If
            If Door >= 2 Then
                Dim Units As String() = Factory.GetBauEinheiten(Factory.Rechteck.X + 0, Factory.Rechteck.Y + 2)
                For Each ID In Units
                    Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(ID, Spieler.Spieler, Factory.Rechteck.X + 0, Factory.Rechteck.Y + 2, False)
                    Dim PFS As Wegsuchsystem = Nothing
                    For I = 0 To PFS2.Count - 1
                        If PFS2(I).Einheit.EinheitenID = ID Then
                            PFS = PFS2(I)
                            Exit For
                        End If
                    Next
                    If PFS Is Nothing Then
                        PFS = New Wegsuchsystem(Unit, Unit.X, Unit.Y, Schlachtfeld, -1, True, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren, True)
                        PFS2.Add(PFS)
                    End If
                    Dim Score2 As Single = ScoreUnitBuild(Unit, PFS, UndestroyableUnits, Enemys, AverageSpendFonds, ExtraFonds, DirectsToIndirects)
                    If BuildUnits.Count > 0 Then
                        'Save best Unit(s)
                        If Score2 < Score + WIDE And Score2 > Score - WIDE Then
                            BuildUnits.Add(Unit)
                            If Score2 > Score Then Score = Score2
                        ElseIf Score2 > Score Then
                            Score = Score2
                            BuildUnits.Clear()
                            BuildUnits.Add(Unit)
                        End If
                    Else
                        Score = Score2
                        BuildUnits.Add(Unit)
                    End If
                Next
                Door -= 2
            End If
            If Door >= 1 Then
                Dim Units As String() = Factory.GetBauEinheiten(Factory.Rechteck.X - 1, Factory.Rechteck.Y + 2)
                For Each ID In Units
                    Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(ID, Spieler.Spieler, Factory.Rechteck.X - 1, Factory.Rechteck.Y + 2, False)
                    Dim PFS As Wegsuchsystem = Nothing
                    For I = 0 To PFS1.Count - 1
                        If PFS2(I).Einheit.EinheitenID = ID Then
                            PFS = PFS1(I)
                            Exit For
                        End If
                    Next
                    If PFS Is Nothing Then
                        PFS = New Wegsuchsystem(Unit, Unit.X, Unit.Y, Schlachtfeld, -1, True, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren, True)
                        PFS1.Add(PFS)
                    End If
                    Dim Score2 As Single = ScoreUnitBuild(Unit, PFS, UndestroyableUnits, Enemys, AverageSpendFonds, ExtraFonds, DirectsToIndirects)
                    If BuildUnits.Count > 0 Then
                        'Save best Unit(s)
                        If Score2 < Score + WIDE And Score2 > Score - WIDE Then
                            BuildUnits.Add(Unit)
                            If Score2 > Score Then Score = Score2
                        ElseIf Score2 > Score Then
                            Score = Score2
                            BuildUnits.Clear()
                            BuildUnits.Add(Unit)
                        End If
                    Else
                        Score = Score2
                        BuildUnits.Add(Unit)
                    End If
                Next
                Door -= 1
            End If

            If Score > MinBuildScore Then
                Dim Unit As ObjektEinheit = BuildUnits(Zufallszahl(0, BuildUnits.Count - 1))
                GebaeudeAuswaehlen(KIModiExtern.FabrikBauen, Factory, Unit, 4)
                Dim Fonds As Integer = Factory.Variablen(1).Wert
                'So now we know how much fonds we've spend already!
                Fonds -= Factory.Variablen(1).Wert
                ExtraFonds = AverageSpendFonds - Fonds
                Build = True
                newUnitsArrived = True
            End If
        End While
    End Sub
#End Region 'Done
#Region "Move"
    ''' <summary>
    ''' Returns all Fields overwhich this Unit can move this turn.
    ''' </summary>
    ''' <param name="PFS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetMovableFields(ByVal PFS As Wegsuchsystem) As List(Of Point)
        'All Fields that can be crossed.
        Dim Fields As New List(Of Point)
        'Go through all fields that are on the Map
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Movepoints As Integer = PFS.GetBewegungspunktekostenReal(X, Y, Schlachtfeld)
                'Can we reach this field in this turn.
                If Movepoints >= 0 Then
                    If Movepoints <= PFS.Einheit.Bewegungspunkte Then
                        Dim Freefield As Boolean = False
                        'Check if this field is true
                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                            Freefield = True
                        ElseIf X = PFS.Einheit.X And Y = PFS.Einheit.Y Then
                            Freefield = True
                        Else
                            Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                            If Unit.EinheitenID = PFS.Einheit.EinheitenID Then 'Same Unit?
                                If Unit.getKP < 10 Then 'Less than 10 HP we could join here.
                                    Freefield = True
                                End If
                            End If
                        End If
                        If Freefield Then
                            Fields.Add(New Point(X, Y))
                        End If
                    End If
                End If
            Next
        Next
        Return Fields
    End Function
    ''' <summary>
    ''' This Returns all Actions that can be done at this Location 
    ''' We don't check if this is useful or clever. However!
    ''' </summary>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetActions(ByVal Field As Point, ByVal Unit As ObjektEinheit) As List(Of KIModiExtern)
        Dim Actions As New List(Of KIModiExtern)
        'Is this Field Clear?
        Dim FieldIsClear As Boolean = False
        If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Schlachtfeld) Is Nothing Or (Field.X = Unit.X And Field.Y = Unit.Y) Then
            FieldIsClear = True
        End If
        'Can we wait on this field?
        If FieldIsClear Then
            Actions.Add(KIModiExtern.Warten)
        Else
            If Unit.Bewegungsart = MovementSorts.Hoellium.ToString Then
                If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Schlachtfeld).GetSpieler.Team <> Spieler.Team Then
                    'Ozziums have no problem to move  over Enemy-Units
                    Actions.Add(KIModiExtern.Warten)
                End If
            End If
        End If

        'Can we load this Unit to another one?
        If CanLoadUnit(Unit, Field) Then
            Actions.Add(KIModiExtern.Fracht)
        End If
        'Can this Unit join at this place
        If CanJoin(Unit, Field) Then
            Actions.Add(KIModiExtern.Einen)
        End If
        'Actions that can be done when no Unit stands here.
        If FieldIsClear Then
            'Can we Capture on this field?
            If CanCapture(Field.X, Field.Y, Unit) Then
                Actions.Add(KIModiExtern.Besetzen)
            End If
            'Can we Attack an Unit
            If CanAttack(Unit, Field) Then
                Actions.Add(KIModiExtern.Angriff)
            End If
            'can this Unit hide or unhide?
            If Unit.KannTarnen = True Then
                'Is this Unit hide!
                If Unit.IsGetaucht = True Then
                    Actions.Add(KIModiExtern.Auftauchen)
                Else
                    Actions.Add(KIModiExtern.Tarnen)
                End If
            End If
            If FieldIsClear Then
                'All Abilities this Unit can do?
                Dim Abilities As String() = Unit.Faehigkeit.ToLower.Split("+")
                For I = 0 To Abilities.Length - 1
                    Select Case Abilities(I)
                        Case "explosion"
                            'This Unit can explode Boom!
                            Actions.Add(KIModiExtern.Explosion)
                        Case "feuerrakete"
                            'This Unit can launch an unhide Rocket?
                            Actions.Add(KIModiExtern.Leuchtrakete)
                        Case "truppenbau" 'We can build a Unit
                            If DataSettings.CommanderWarsGameModus = CommanderWarsGameModi.AdvanceWarsDC Then
                                If Unit.Munition > 0 Then
                                    If Unit.HasPlaceforLoading Then
                                        Actions.Add(KIModiExtern.FlugzeugtraegerBau)
                                    End If
                                End If
                            ElseIf Unit.HasPlaceforLoading Then
                                Actions.Add(KIModiExtern.FlugzeugtraegerBau)
                            End If
                        Case "reparieren" 'We can repair a Unit
                            If CanGiveRation(Unit, Field) Then
                                Actions.Add(KIModiExtern.Reparieren)
                            End If
                            'Building normal Units is left out for the moment.
                        Case "ration", "rationsame"
                            'Can this unit give ration to other units here.
                            If CanGiveRation(Unit, Field) Then
                                Actions.Add(KIModiExtern.Ration)
                            End If
                    End Select
                Next
            End If
            'Can we launch a Rocket from here?
            If CanLaunchRocket(Unit, Field) Then
                Actions.Add(KIModiExtern.SiloZuenden)
            End If
            'Can this Unit unload Units
            If CanUnloadUnits(Unit, Field) Then
                Actions.Add(KIModiExtern.Entladen)
            End If
            'Can this Unit send to another Map
            If CanSendUnit(Unit, Field) Then
                Actions.Add(KIModiExtern.EinheitSchicken)
            End If
            'Can we create a CO Unit
            If CanCreateCOUnit(Unit, Field) Then
                Actions.Add(KIModiExtern.CreateKOEinheit)
            End If
            'Can we build a temporary Base?
            If CanBuildTempBase(Unit, Field) Then
                Actions.Add(KIModiExtern.TemporaereBasisbauen)
            End If
        End If

        Return Actions
    End Function
    ''' <summary>
    ''' Checks wether we can capture a Building here or not.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanCapture(ByVal X As Integer, ByVal Y As Integer, ByVal Unit As ObjektEinheit) As Boolean
        'Is field clear
        If IsNothing(Objektverwalter.Spielfeld.Landschaften(X, Y, Unit.GetMap).Gebaeude) = False Then
            'Can the Unit capture
            If Unit.KannBesetzen = True Then
                'Are the Capturepoints higer than 0
                If Objektverwalter.Spielfeld.Landschaften(X, Y, Unit.GetMap).Gebaeude.Besetzung > 0 Then
                    'Is the Building Team an Enemy Team
                    If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Landschaften(X, Y, Unit.GetMap).Gebaeude.Spieler).Team = Objektverwalter.Spielfeld.Spieler(Unit.Spieler).Team Then
                        Return True
                    End If
                End If
            End If
        End If
    End Function
    ''' <summary>
    ''' Can we join at this Field
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanJoin(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        If Unit.X <> Field.X Or Unit.Y <> Field.Y Then
            If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Schlachtfeld) IsNot Nothing Then
                'Are the Unit IDs equal
                If Unit.EinheitenID = Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).EinheitenID Then
                    'Is the Unit from this Player
                    If Unit.Spieler = Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Spieler Then
                        'Are the HP smaller 90
                        If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).KP <= 90 Then
                            Return True
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can a Unit give Ration on this field to our Units?
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanGiveRation(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        'Go through the 4 Fields around this Field?
        For I = 0 To 3
            Select Case I
                Case 0
                    Field.Y -= 1
                Case 1
                    Field.Y += 1
                    Field.X += 1
                Case 2
                    Field.Y += 1
                    Field.X -= 1
                Case 3
                    Field.Y -= 1
                    Field.X -= 1
            End Select
            'Is this field on the Map.
            If Objektverwalter.Spielfeld.OnMap(Field.X, Field.Y) Then
                'Is this field clear?
                If IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)) = False Then
                    'Are their any Units that can get Ration?
                    If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Spieler = Unit.Spieler Then
                        If Unit.Faehigkeit = "RationSame" Then
                            If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Objektverwalter.Spielfeld.AktuelleEinheit.GetMap).IsGroundUnit = Unit.IsGroundUnit Or _
                                Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Objektverwalter.Spielfeld.AktuelleEinheit.GetMap).IsFlyingUnit = Unit.IsFlyingUnit Or _
                                Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Objektverwalter.Spielfeld.AktuelleEinheit.GetMap).IsSeaUnit = Unit.IsSeaUnit Then
                                Return True
                            End If
                        Else
                            Return True
                        End If
                    End If
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Can this Unit launch a Rocket from here?
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanLaunchRocket(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        'Can this Unit capture Rocket
        If Unit.KannBesetzen = True Then
            'Is their a Building
            If IsNothing(Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).Gebaeude) = False Then
                'Has this Building a Rocket to launch?
                If Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).Gebaeude.Angriff = ObjektGebaeude.Angriffe.Silo Then
                    Return True
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can we create a CO Unit?
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanCreateCOUnit(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        'Is it allowed to build CO Units
        If Objektverwalter.Spielfeld.Regeln.KOSystem > KOSysteme.Gabe_Modus Then
            'Do we have a CO Unit or not
            If Objektverwalter.Spielfeld.Spieler(Unit.Spieler).KOS(0).GetKOUnit Is Nothing Then
                Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Schlachtfeld).Gebaeude
                'Have we enough Fonds to build this CO-Unit
                If Unit.Kosten / 2 <= Spieler.Fonds Then
                    If Not G Is Nothing Then
                        'Is this our Building here?
                        If G.GetSpieler.Team = Unit.GetSpieler.Team Then
                            'Can this Building upgrate our Units
                            If G.GetBaulisteThisPlayer.Contains(Unit.EinheitenID) Or (G.Angriff = ObjektGebaeude.Angriffe.HQ And Unit.IsGroundUnit) Then
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can this Unit send to another Map
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanSendUnit(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then
            Dim SendeMap As Integer = Unit.GetSendeMap
            If SendeMap >= 0 Then
                If Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, SendeMap) Is Nothing Then
                    Return True
                Else
                    Return False
                End If
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Can this Unit send to another Map
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanUnloadUnits(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        'Has this Unit the Abilitie to load a Unit
        If Unit.Ladung.Length > 0 Then
            'Is there a Unit
            If IsNothing(Unit.Ladung(0)) = False Then
                'Are we able to unload Units from this Field
                If Array.IndexOf(Unit.EntladungsUntergrund, Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).getID) >= 0 Then

                    For I = 0 To 3
                        Select Case I
                            Case 0
                                Field.Y -= 1
                            Case 1
                                Field.Y += 1
                                Field.X += 1
                            Case 2
                                Field.Y += 1
                                Field.X -= 1
                            Case 3
                                Field.Y -= 1
                                Field.X -= 1
                        End Select
                        'Is this field on the Map
                        If Objektverwalter.Spielfeld.OnMap(Field.X, Field.Y) Then
                            'Can we unload one of our loaded Units here
                            For I2 = 0 To Unit.Ladung.Length - 1
                                'Is a Unit at this place
                                If Unit.Ladung(I2) IsNot Nothing Then
                                    'Can this Unit be unload to this place?
                                    If Objektverwalter.Bewegungskosten(Unit.Ladung(I2), Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).getID, Objektverwalter.Spielfeld.Regeln.Wetter, Field.X, Field.Y) > 0 And IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)) = True Then
                                        Return True
                                    End If
                                End If
                            Next
                        End If
                    Next
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can we load this Unit to another on this Field?
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanLoadUnit(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        'Is their a Transporter?
        If IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)) = False Then
            'Can the Transporter load this Unit?
            If FindElement(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).GeladeneEinheitenIDs, Unit.EinheitenID) >= 0 Then
                Dim NumberOfLoadedUnits As Integer = 0
                'Has the Transporter space for our Unit?.
                For I = 0 To Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Ladung.Length - 1
                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Ladung(I)) Then
                        NumberOfLoadedUnits += Unit.Get_Unit_Space()
                        If NumberOfLoadedUnits <= Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Ladung.Length Then
                            Return True
                        Else
                            Return False
                        End If
                    Else
                        NumberOfLoadedUnits += Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap).Ladung(I).Get_Unit_Space()
                    End If
                Next
            Else
                Return False
            End If
        Else
            Return False
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can this Unit attack an Enemy Unit
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanAttack(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        Dim Kreis(,) As Integer = {}
        Dim MaximalReichweite As Integer = -1
        'get min Firerange
        Dim Minmalreichweite As Integer = Unit.MinimaleReichweite
        'get max Firerange
        MaximalReichweite = Unit.MaximaleReichweite

        Dim Stelle As Integer = Array.IndexOf(Objektverwalter.Spielfeld.AktuellerSpieler.KOS(0).WetterartfuerSenker, Objektverwalter.Spielfeld.Regeln.Wetter)
        Kreis = Kreisfunktion(MaximalReichweite)
        If Kreis.Length >= 0 Then
            'Go through all Circles
            For X = 0 To Kreis.GetLength(0) - 1
                For Y = 0 To Kreis.GetLength(1) - 1
                    'Is it a field 
                    If Kreis(X, Y) > 0 Then
                        'Is this field in min and max Firerange
                        If Kreis(X, Y) >= Unit.MinimaleReichweite Or Not Unit.Waffe1 = "Keine" Then
                            'Is this Field on the Map
                            If Objektverwalter.Spielfeld.OnMap(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y) Then
                                If Not Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Hidden Then
                                    'Is there a Unit
                                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap)) = False Then
                                        'Is it an Enemy Unit
                                        If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Spieler).Team = Objektverwalter.Spielfeld.Spieler(Unit.Spieler).Team Then
                                            'Is the Unit visible
                                            If Objektverwalter.Spielfeld.Einheiten(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Sichtbar = True Then
                                                'Indirect Attack
                                                Dim Fernkampf As Boolean = False
                                                If Kreis(X, Y) > 1 Then
                                                    Fernkampf = True
                                                End If
                                                'Hidden?
                                                If (Fernkampf And Objektverwalter.Spielfeld.Einheiten(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).GetTarnung) Then
                                                    Return False
                                                End If
                                                If (Fernkampf And Field.X = Unit.X And Field.Y = Field.Y) Or (Not Fernkampf) Then
                                                    'Can we attack this Unit.
                                                    If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                                        Return True
                                                    End If
                                                End If
                                            End If
                                        End If
                                    ElseIf Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Leben > 0 Then
                                        'There is a terrain with Live
                                        Dim Fernkampf As Boolean = False
                                        If Kreis(X, Y) > 1 Then
                                            Fernkampf = True
                                        End If
                                        'Can we attack this Terrain?
                                        If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                            Return True
                                        End If
                                    ElseIf IsNothing(Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Gebaeude) = False Then
                                        'Here is a building
                                        If Objektverwalter.Spielfeld.Landschaften(Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Gebaeude.Rechteck.X, Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Gebaeude.Rechteck.Y, Unit.GetMap).Gebaeude.GetKP(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, False) > 0 Then
                                            'It has live
                                            If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Landschaften(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, Unit.GetMap).Gebaeude.Spieler).Team = Objektverwalter.Spielfeld.Spieler(Unit.Spieler).Team Then
                                                'It's an Enemy Building
                                                Dim Fernkampf As Boolean = False
                                                If Kreis(X, Y) > 1 Then
                                                    Fernkampf = True
                                                End If
                                                'Can we Attack this building 
                                                If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return False
    End Function
    ''' <summary>
    ''' Can this Unit build a temporary Base?
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanBuildTempBase(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Boolean
        If Unit.Munition > 0 Then
            If Unit.HasMaterial Then
                Dim L As ObjektLandschaft = Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap)
                Select Case L.getID.ToUpper
                    Case "EBENE", "SCHNEE", "WUESTE", "STRAND"
                        Return True
                End Select
            End If
        End If
        Return False
    End Function
#End Region
#Region "Move Scoring"
    ''' <summary>
    ''' Calculates the overall Damage we can do to Enemies here.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Action"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreActionAtPosition(ByVal Unit As ObjektEinheit, ByVal Action As KIModiExtern, ByVal Field As Point, ByVal PFS As Wegsuchsystem, ByVal ThisArmy As Army, ByVal MoveableFields As List(Of Point), Optional ByVal FirstTurn As Boolean = True) As Army.UnitTarget
        'Initial Phase for the Target
        Dim Target As New Army.UnitTarget(0, Action, Field)
        'Real calculation
        'We add the Deffence of this Terrain (including Building Deffence) so we move more often on fields with high Deffence Values (not for Air Units :( )
        If Not Unit.IsFlyingUnit Then
            Target.Score += Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).GetDeckung
        End If

        Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).Gebaeude
        'Some Actions get Bonus Values
        Select Case Action
            Case KIModiExtern.Besetzen 'Capturing
                Target.Score += ScoreCapturing(Unit, Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Unit.GetMap).Gebaeude, PFS)
            Case KIModiExtern.Angriff 'Attacking
                Dim Targets As List(Of Point) = GetAttackFields(Unit, Field)
                Dim Score1 As Double = -1000
                Dim UnitTarget As New List(Of Point)
                Dim LowHP As Boolean = False
                'Loop all Targets and get best Target.
                For I = 0 To Targets.Count - 1
                    Dim Score2 As Double = ScoreAttack(Unit, Field, Targets(I))
                    If Score2 > 0 Then
                        If Objektverwalter.Spielfeld.Einheiten(Targets(I).X, Targets(I).Y, Objektverwalter.Spielfeld.MomentaneSchlacht) IsNot Nothing Then
                            If OnlyLowLiveEnemys(Unit, MoveableFields) Then
                                'we need to adjust this special cases
                                If Score2 < 0.5 Then
                                    Score2 *= AIDatabase.TurnPriority * 20
                                ElseIf Score2 < 1 Then
                                    Score2 *= AIDatabase.TurnPriority * 10
                                ElseIf Score2 < 3 Then
                                    Score2 *= AIDatabase.TurnPriority * 2
                                End If
                            End If
                        End If
                    End If
                    If Score2 > Score1 Then
                        UnitTarget.Clear()
                        UnitTarget.Add(Targets(I))
                        Score1 = Score2
                    ElseIf Score2 = Score1 Then
                        UnitTarget.Add(Targets(I))
                    End If
                Next
                Target.Score += Score1
                If UnitTarget.Count > 0 Then
                    'All Targets have the same Score rating so we select a random one.
                    Target.Target = UnitTarget(Zufallszahl(0, UnitTarget.Count - 1))
                End If
            Case KIModiExtern.Warten 'Waiting
                If SecondTurn Or TurnPriority = FirstTurnPriority.None Then
                    Target.Score = ScoreWait(Unit, Field)
                Else
                    Target.Score = ScoreWait(Unit, Field) / AIDatabase.TurnPriority
                End If
            Case KIModiExtern.SiloZuenden 'Launch Missile
                Dim SiloScore As Vector4 = ScoreSilo(Field)
                Target.Score += SiloScore.Z
                If SiloScore.Z > 0 Then
                    Target.Score += SiloScore.W / 2
                End If
                Target.Target = New Point(SiloScore.X, SiloScore.Y)
                If Target.Score < GetMinimalExplosionScore() Then 'I would say it must be more than 8 points
                    Target.Score = BadActionScore
                End If
            Case KIModiExtern.Explosion 'Explosion of a S-Bomb
                Dim Score As PointF = ExplosionScore(Field.X, Field.Y, 5, 3)
                Target.Score += Score.X
                If Score.X > 0 Then
                    Target.Score += Score.Y / 2 'Two Units give an extra point
                End If
                If Not Unit.Treibstoff - Distance(Unit.GetLocation, Field) - Unit.Treibstoffverbrauch < Unit.Bewegungspunkte * 1.5 Then
                    Target.Score -= Unit.GetEinheitenWert() / (AIDatabase.BigGeneralFondsDivider * 3)
                ElseIf Target.Score < GetMinimalExplosionScore() Then 'I would say it must be more than 8 points
                    Target.Score = BadActionScore
                End If
            Case KIModiExtern.Einen 'Join
                Target.Score += ScoreJoin(Unit, Field)
            Case KIModiExtern.Ration 'Should we give Ration?
                Target.Score += ScoreRation(Field, Unit)
            Case KIModiExtern.Reparieren 'Should we repair a Unit?
                Dim Scores As New List(Of Vector3)
                'Loop through all Neightbour Fields
                Dim L As ObjektLandschaft = Wegsuchsystem.getFeldRundrum(Field.X, Field.Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                While L IsNot Nothing
                    'Score Repair here
                    Dim S As Double = ScoreRepair(New Point(L.KooX, L.KooY), Unit)
                    'Check if this field is better than the old one.
                    If Scores.Count > 0 Then
                        If Scores(0).Z < S Then
                            Scores.Clear()
                            Scores.Add(New Vector3(L.KooX, L.KooY, S))
                        ElseIf Scores(0).Z = S Then
                            Scores.Add(New Vector3(L.KooX, L.KooY, S))
                        End If
                    Else
                        Scores.Add(New Vector3(L.KooX, L.KooY, S))
                    End If
                    'get next Field
                    L = Wegsuchsystem.getFeldRundrum(Field.X, Field.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                End While
                If Scores.Count > 0 Then
                    Dim V As Vector3 = Scores(Zufallszahl(0, Scores.Count - 1))
                    Target.Score += V.Z
                    Target.Target = New Point(V.X, V.Y)
                End If
        End Select

        'Is here a Building?
        If Building IsNot Nothing Then
            'Is it an Enemy Building?
            If Building.GetSpieler.Team <> Spieler.Team Then
                'Enemy Buildings should be blocked if Units could be produced here!
                Target.Score += GetCaptureValue(Building, Unit)
            Else
                Target.Score -= GetCaptureValue(Building, Unit)
            End If
        End If
        'We won't do Actions with such a low Score
        If Target.Score > -Database.ThousandFonds Then
            Target.Score -= NextTurnDamage(Unit, Field, ThisArmy)
        End If
        Return Target
    End Function

    Private Function OnlyLowLiveEnemys(ByVal Unit As ObjektEinheit, ByVal Targets As List(Of Point)) As Boolean
        For i = 0 To Targets.Count - 1
            Dim TargetPoints As List(Of Point) = GetAttackFields(Unit, Targets(i))
            For i2 = 0 To TargetPoints.Count - 1
                If Objektverwalter.Spielfeld.Einheiten(TargetPoints(i2).X, TargetPoints(i2).Y, Objektverwalter.Spielfeld.MomentaneSchlacht) IsNot Nothing Then
                    If Objektverwalter.Spielfeld.Einheiten(TargetPoints(i2).X, TargetPoints(i2).Y, Objektverwalter.Spielfeld.MomentaneSchlacht).Leben > AIDatabase.LowHPUnit Then
                        Return False
                    End If
                End If
            Next
        Next
        Return True
    End Function
    ''' <summary>
    ''' Scores how effectiv join would be here.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreJoin(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Double

        Dim Score As Double = 0
        Dim JoinUnit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Schlachtfeld)
        If Unit.X <> Field.X Or Unit.Y <> Field.Y Then
            'Did the Join Unit move already?
            If Not JoinUnit.HatsichBewegt Then
                'It didn't
                Score -= JoinUnit.getKP / 2 'Make it a little bit less efficient to join here.
            End If
            'Get Live of both Units
            Dim Live As Single = Unit.Leben + JoinUnit.Leben
            Select Case Live
                Case Is > 90
                    'Special CO Behaviour
                    Select Case Spieler.KOS(0).KOID
                        Case "SENSEI"
                            'Sensei during COP or SCOP ignores this Rule in Order to earn extra Fonds
                            Select Case Spieler.KOS(0).Gabemodus
                                Case ObjektKO.Gabemodi.Gabe 'SCOP
                                    If JoinUnit.EinheitenID = "INF" And Unit.EinheitenID = "INF" Then 'Both are Infis
                                        If JoinUnit.Leben <= 90 And Unit.EinheitenID <= 90 Then 'Both have less or equal to 9 HP
                                            Score += getKP(Live) / 2 + (getKP(Live - 100) * Unit.GetEinheitenWert / 10) / AIDatabase.LowGeneralFondsDivider '300 Fonds divider
                                        End If
                                    End If
                                Case ObjektKO.Gabemodi.Spezialgabe, ObjektKO.Gabemodi.Doppelgabe
                                    If JoinUnit.EinheitenID = "MECH" And Unit.EinheitenID = "MECH" Then 'Both are Mech Units
                                        If JoinUnit.Leben <= 90 And Unit.EinheitenID <= 90 Then 'Both have less or equal to 9 HP
                                            Score += getKP(Live) / 2 + (getKP(Live - 100) * Unit.GetEinheitenWert / 10) / AIDatabase.LowGeneralFondsDivider '300 Fonds divider
                                        End If
                                    End If
                            End Select
                        Case Else 'All other CO's won't join here.
                            Score = BadActionScore 'Not very clever to join. both or one Unit is able to fight. back
                    End Select
                Case Is >= 50 'Join here.
                    Score += getKP(Live) / 2
                Case Else
                    'Live is that low
                    Score = BadActionScore 'Not very clever to join. Better Meatwall here.
            End Select
            'It's bad to join on Buildings(except for Sensei during COP or SCOP)
            If Not (Spieler.KOS(0).KOID = "SENSEI" And Spieler.KOS(0).Gabemodus <> ObjektKO.Gabemodi.Keine) Then
                Dim RepairUnit As ObjektEinheit = Unit
                For I = 0 To 1
                    If I = 1 Then RepairUnit = JoinUnit
                    Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(RepairUnit.X, RepairUnit.Y, RepairUnit.GetMap).Gebaeude
                    If Building IsNot Nothing Then 'Here's a Building
                        'This Building can resupply
                        If Building.Versorung Then
                            'Get Construction List of the Building
                            Dim BuildList() As String = {}
                            If Building.GetBauliste.Length > 0 Then
                                BuildList = Building.GetBauliste
                            Else 'Towns HQ's get the Base Building List
                                BuildList = ObjektLadeklasse.GetBauliste("Basis")
                            End If
                            'This Unit can be repaired by the Building?
                            If BuildList.Contains(RepairUnit.EinheitenID) Then
                                'Calculate Repair Points
                                Dim HP As Integer = RepairUnit.getKP + Spieler.KOS(0).GebaeudeHeilung
                                If HP > 10 Then HP = 10
                                HP -= RepairUnit.getKP
                                Score -= (HP + (RepairUnit.GetEinheitenKosten / 10) / AIDatabase.BigGeneralFondsDivider)
                            End If
                        End If
                    End If
                Next
            End If
        Else
            Score = -100
        End If
        Return Score
    End Function
    ''' <summary>
    ''' This calculates the Damage Score we may recieve next Turn.
    ''' So we need to avoid to move here.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function NextTurnDamage(ByVal Unit As ObjektEinheit, ByVal Field As Point, ByVal DefendingArmy As Army) As Double
        'What do we do here?
        'Good question i guess!
        'We try to calculate the Thread our Enemy can give here.
        Dim ThreatScore As Double = 0
        Dim UpperScore As Double = 0
        Dim LeftScore As Double = 0
        Dim RightScore As Double = 0
        Dim LowerScore As Double = 0
        If EnemyArmy IsNot Nothing Then
            'Calculating threat!
            For Each EnemyData In EnemyArmy.Units
                Dim Enemy As ObjektEinheit = EnemyData.Unit
                'Getting the Unit
                If Enemy IsNot Nothing Then 'Enemy?
                    'Real Enemy
                    If Enemy.Leben > 0 Then
                        If Enemy.GetSpieler.Team <> Spieler.Team Then
                            If Enemy.MaximaleReichweite > 1 Then 'Indirect Unit
                                If GetDistance(Enemy.GetLocation, Field) <= Enemy.MaximaleReichweite And GetDistance(Enemy.GetLocation, Field) >= Enemy.MinimaleReichweite Then 'In Range?
                                    Dim Score As Double = ScoreAttack(Enemy, Enemy.GetLocation, Field, Unit)
                                    Dim Divider As Single = 1
                                    For Each Soldier In DefendingArmy.Units
                                        If Soldier.Unit.GetLocation <> Unit.GetLocation Then
                                            Dim Found As Boolean = False
                                            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                                                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                                                    If Soldier.PFS.GetBewegungspunktekostenReal(X1, Y1, Schlachtfeld) >= 0 Then
                                                        If GetDistance(Enemy.X, Enemy.Y, X1, Y1) <= Enemy.MaximaleReichweite And GetDistance(Enemy.X, Enemy.Y, X1, Y1) >= Enemy.MinimaleReichweite Then 'In Range?
                                                            If Soldier.Unit.GetEinheitenWert > Unit.GetEinheitenWert Then
                                                                Divider += AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.NextTurnDeffenceStrategy
                                                            ElseIf Not MeatwallUnit(Soldier.Unit) Then
                                                                Divider += (AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.NextTurnDeffenceStrategy / 2)
                                                            Else
                                                                Divider += (AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.NextTurnDeffenceStrategy / 4)
                                                            End If
                                                            Found = True
                                                            Exit For
                                                        End If
                                                    End If
                                                Next
                                                If Found Then Exit For
                                            Next
                                        End If
                                    Next
                                    ThreatScore += Score / Divider
                                    Continue For
                                End If
                            End If
                            If Enemy.MinimaleReichweite = 1 Or Enemy.Waffe1 <> "Keine" Then
                                'Sorting out a lot of Units in Order to improve AI-Speed
                                If GetDistance(Enemy.X, Enemy.Y, Field.X, Field.Y) + 1 <= Enemy.Bewegungspunkte Then
                                    Dim PFS As Wegsuchsystem = EnemyData.PFS
                                    'In the worst case we could be Attacked from four Sides with Directs! We'll going to test all sides compare it with the current value and set it here.
                                    If Field.X > 0 Then
                                        If PFS.GetBewegungspunktekostenReal(Field.X - 1, Field.Y, Schlachtfeld) >= 0 Then
                                            Dim Score As Double = ScoreAttack(Enemy, New Point(Field.X - 1, Field.Y), Field, Unit)
                                            If Score > LeftScore Then
                                                LeftScore = Score
                                                Continue For
                                            End If
                                        End If
                                    End If
                                    If Field.X + 1 < Objektverwalter.Spielfeld.Breite Then
                                        If PFS.GetBewegungspunktekostenReal(Field.X + 1, Field.Y, Schlachtfeld) >= 0 Then
                                            Dim Score As Double = ScoreAttack(Enemy, New Point(Field.X + 1, Field.Y), Field, Unit)
                                            If Score > RightScore Then
                                                RightScore = Score
                                                Continue For
                                            End If
                                        End If
                                    End If
                                    If Field.Y > 0 Then
                                        If PFS.GetBewegungspunktekostenReal(Field.X, Field.Y - 1, Schlachtfeld) >= 0 Then
                                            Dim Score As Double = ScoreAttack(Enemy, New Point(Field.X, Field.Y - 1), Field, Unit)
                                            If Score > UpperScore Then
                                                UpperScore = Score
                                                Continue For
                                            End If
                                        End If
                                    End If
                                    If Field.Y + 1 < Objektverwalter.Spielfeld.Hoehe Then
                                        If PFS.GetBewegungspunktekostenReal(Field.X, Field.Y + 1, Schlachtfeld) >= 0 Then
                                            Dim Score As Double = ScoreAttack(Enemy, New Point(Field.X, Field.Y + 1), Field, Unit)
                                            If Score > LowerScore Then
                                                RightScore = LowerScore
                                                Continue For
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        End If
        'So what do we have now?
        'We know which are the Attacks that might come to our Unit, now we need to reduce them?
        'As we normally move some Units and not all Indirects will attack our small little Unit. (Here comes the guessing part again!)
        'Here i try to reduce the Direct Damage
        Dim P As Point = Field
        'loop through neighbours
        For I = 0 To 3
            Select Case I
                Case 0
                    P.X -= 1
                Case 1
                    P.X += 1
                    P.Y -= 1
                Case 2
                    P.Y += 1
                    P.X += 1
                Case 3
                    P.Y += 1
                    P.X -= 1
            End Select
            'The more Units could reach the Neighbour field the better it is for us.
            Dim Divider As Single = 1
            For Each Soldier In DefendingArmy.Units
                If Soldier.Unit.GetLocation <> Unit.GetLocation Then
                    If Objektverwalter.Spielfeld.OnMap(P.X, P.Y) Then
                        If Soldier.PFS.GetBewegungspunktekostenReal(P.X, P.Y, Schlachtfeld) >= 0 Then
                            If MeatwallUnit(Soldier.Unit) Then
                                Divider += AIDatabase.Get_Average_MeatWallBonus
                            Else
                                Divider += AIDatabase.Get_Average_Next_Turn_Deffence_Strategy
                            End If
                        End If
                    End If
                End If
            Next
            Select Case I
                Case 0
                    ThreatScore += LeftScore / Divider
                Case 1
                    ThreatScore += UpperScore / Divider
                Case 2
                    ThreatScore += RightScore / Divider
                Case 3
                    ThreatScore += LowerScore / Divider
            End Select
        Next
        Return ThreatScore
    End Function
    ''' <summary>
    ''' Scores the best Silo Target.
    ''' X=X
    ''' Y=Y
    ''' Z=Score
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreSilo(ByVal Field As Point) As Vector4
        Dim Silo As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Schlachtfeld).Gebaeude
        Dim Targets As New List(Of Vector4)
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Score As PointF = ExplosionScore(X, Y, Silo.Schaden, Silo.Reichweite)
                If Targets.Count > 0 Then
                    If Targets(0).Z < Score.X Then
                        Targets.Clear()
                        Targets.Add(New Vector4(X, Y, Score.X, Score.Y))
                    ElseIf Targets(0).Z = Score.X Then
                        Targets.Add(New Vector4(X, Y, Score.X, Score.Y))
                    End If
                Else
                    Targets.Add(New Vector4(X, Y, Score.X, Score.Y))
                End If

            Next
        Next
        If Targets.Count > 0 Then
            Return Targets(Zufallszahl(0, Targets.Count - 1))
        Else
            Return New Vector4(-1, -1, -10000, -1)
        End If
    End Function
    ''' <summary>
    ''' Scores how effectiv an Explosion or Silo would be here.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Damage"></param>
    ''' <param name="Radius"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ExplosionScore(ByVal X As Integer, ByVal Y As Integer, ByVal Damage As Integer, ByVal Radius As Integer) As PointF
        Dim Geld As Integer = 0
        Dim Kreis(,) As Integer = Kreisfunktion(Radius)
        Dim PlayerPrio As Double = AIDatabase.GetHighestPlayerPrio
        Dim UnitCount As Integer = 0
        Dim OwnUnits As Integer = 0
        Dim Prio As UInt64 = 0
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= 0 Then
                    If Objektverwalter.Spielfeld.OnMap(X - Radius + X1, Y - Radius + Y1) Then
                        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht)) = False Then
                            Dim VerlorenesLeben As Integer = Damage
                            If VerlorenesLeben - Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).getKP > 0 Then
                                If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).getKP > 1 Then
                                    VerlorenesLeben = Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).getKP
                                Else
                                    If Objektverwalter.Spielfeld.Regeln.GebaeudeZerstoerung Then
                                        VerlorenesLeben = 1
                                    Else
                                        VerlorenesLeben = 0
                                    End If
                                End If
                            End If
                            If VerlorenesLeben > 0 Then
                                If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).Spieler).Team = Objektverwalter.Spielfeld.AktuellerSpieler.Team Then
                                    'Our own Unit
                                    '-Money Damage*Unit Value
                                    Geld -= (Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).Kosten * VerlorenesLeben / 10) * (PlayerPrio * 2)
                                    Prio += PlayerPrio * 2
                                    UnitCount += 1
                                    OwnUnits += 1
                                Else
                                    'An Enemy Unit
                                    '+Money Damage*Player Priority
                                    Geld += Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).Kosten * VerlorenesLeben / 10 * AIDatabase.GetPlayerData(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).Spieler).PlayerPriority
                                    Prio += AIDatabase.GetPlayerData(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, ObjektSpielfeld.Bodenschlacht).Spieler).PlayerPriority
                                    UnitCount += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If Prio = 0 Or Geld = 0 Then
            Return New PointF(0, 0)
        Else
            Return New PointF(Geld * UnitCount / (AIDatabase.BigGeneralFondsDivider * Prio), UnitCount - OwnUnits)
        End If
    End Function
    ''' <summary>
    ''' Scores how good giving Ration would be here.
    ''' </summary>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreRation(ByVal Field As Point, ByVal Unit As ObjektEinheit) As Double
        Dim Score As Double = 0
        'Go through the 4 Fields around this Field?
        For I = 0 To 3
            Select Case I
                Case 0
                    Field.Y -= 1
                Case 1
                    Field.Y += 1
                    Field.X += 1
                Case 2
                    Field.Y += 1
                    Field.X -= 1
                Case 3
                    Field.Y -= 1
                    Field.X -= 1
            End Select
            Score += ScoreRationField(Field, Unit)
        Next
        If Score > 0 Then
            Return Score
        Else
            Return BadActionScore
        End If
    End Function
    ''' <summary>
    ''' Scores how good it would be to give Ration to this Field.
    ''' </summary>
    ''' <param name="Field"></param>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreRationField(ByVal Field As Point, ByVal Unit As ObjektEinheit) As Double
        Dim Score As Double = 0
        'Is this field on the Map.
        If Objektverwalter.Spielfeld.OnMap(Field.X, Field.Y) Then
            'Is this field clear?
            If IsNothing(Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)) = False Then
                Dim RationUnit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)
                Score += ScoreRationUnit(RationUnit)
            End If
        End If
        Return Score
    End Function
    Private Function ScoreRationUnit(ByVal RationUnit As ObjektEinheit) As Double
        Dim Score As Double = 0
        'Are their any Units that can get Ration?
        If RationUnit.Spieler = Spieler.Spieler Then
            If RationUnit.SpritMax > 0 Then 'This Unit can have Fuel
                If RationUnit.Treibstoff <= RationUnit.SpritMax * MinimalerTreibstoff Then
                    Score += 4 'Less than 1/3 of Max Fuel needs some resupply
                ElseIf RationUnit.Treibstoff <= RationUnit.SpritMax / 2 Then
                    Score += 2 'Less than 1/2 of Max Fuel needs not very urgent resupply
                ElseIf RationUnit.Treibstoff <= RationUnit.SpritMax * 3 / 4 Then
                    Score += 0.5 'Less than 3/4 of Max Fuel needs not  urgent resupply
                End If
            End If
            If RationUnit.MunitionMax > 0 Then 'This Unit can have Ammo
                If RationUnit.Munition <= RationUnit.MunitionMax * MinimaleMunition Then
                    Score += 4 'Less than 1/3 of Max Ammo needs some resupply
                ElseIf RationUnit.Munition <= RationUnit.MunitionMax / 2 Then
                    Score += 2 'Less than 1/2 of Max Ammo needs not very urgent resupply
                ElseIf RationUnit.Munition <= RationUnit.MunitionMax * 3 / 4 Then
                    Score += 0.5 'Less than 3/4 of Max Ammo needs not  urgent resupply
                End If
            End If
        End If
    End Function
    ''' <summary>
    ''' Scores how efficient it is to repair a Unit
    ''' </summary>
    ''' <param name="Field"></param>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreRepair(ByVal Field As Point, ByVal Unit As ObjektEinheit) As Double
        Dim Score As Double = ScoreRationField(Field, Unit) 'Calculate Ration Bonus
        Dim RepairUnit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Field.X, Field.Y, Unit.GetMap)
        If RepairUnit IsNot Nothing Then
            If RepairUnit.getKP <= 9 Then
                If Spieler.Fonds >= RepairUnit.GetEinheitenKosten / 10 Then
                    Score += (RepairUnit.GetEinheitenKosten / 10) / AIDatabase.BigGeneralFondsDivider
                End If
            End If
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Returns wether we use this Unit to create a Meatwall in Order to defend more expansive Units for a Counterstrike!
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function MeatwallUnit(ByVal Unit As ObjektEinheit) As Boolean
        If Unit.MinimaleReichweite = 1 Or Unit.Waffe1 <> "Keine" Then
            If Unit.getKP <= 3 Then Return True 'Units with less than 3HP get Meatwall Units.
            If Unit.GetEinheitenWert <= AIDatabase.MechCosts Then Return True
        End If
        Return False
    End Function
    ''' <summary>
    ''' Scores how efficient it is Wait at this Position!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    ''' 
    Private Function ScoreWait(ByVal Unit As ObjektEinheit, ByVal Field As Point) As Double
        Dim Score As Double = 0
        'Scores the Repaircosts to wait here
        If Not Unit.IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
            Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Field.X, Field.Y, Schlachtfeld).Gebaeude
            If Building IsNot Nothing Then
                If Building.Spieler = Spieler.Spieler Then
                    Dim BList() As String = Building.GetBauliste(Building.Spieler)
                    If Building.Versorung And BList.Length = 0 Then
                        BList = ObjektLadeklasse.GetBauliste("BASIS")
                    End If
                    If BList.Contains(Unit.EinheitenID) Then
                        'HP Score
                        Dim Repair As Integer = 0
                        If Unit.getKP + Spieler.KOS(0).GebaeudeHeilung > 10 Then
                            Repair = 10 - Unit.getKP
                        Else
                            Repair = Spieler.KOS(0).GebaeudeHeilung
                        End If
                        'Ammo Score

                        If Unit.GetEinheitenKosten > AIDatabase.MechCosts And Unit.Leben < AIDatabase.LowHPUnit Then
                            Score += (Unit.GetEinheitenKosten * Repair) / (10 * AIDatabase.BigGeneralFondsDivider) * AIDatabase.TurnPriority
                        Else
                            Score += (Unit.GetEinheitenKosten * Repair) / (10 * AIDatabase.BigGeneralFondsDivider)
                        End If

                        Score += ScoreRationUnit(Unit)
                    End If
                End If
            End If
        End If
        Dim Wetter As ObjektSpielfeld.Wetterarten = ObjektSpielfeld.Wetterarten.Sonne
        Dim Enemys As New List(Of Integer)
        Dim Fullfilled As Boolean = True
        'Ideal Enemy Distance?
        For Each Enemy In EnemyArmy.Units
            'Are we at a Position where we need to be defended by an Allied Unit
            Wetter = Objektverwalter.Spielfeld.Regeln.GetWetterBeiSpieler(Enemy.Unit.Spieler)
            'Distance is Higher than Movement Range continue
            Dim Dis As Integer = GetDistance(Field.X, Field.Y, Enemy.Unit.X, Enemy.Unit.Y)
            If Dis >= Enemy.Unit.GetMaximalReichweite(Wetter) + 1 Then
                Continue For
            End If

            Dim Movecosts As Integer = Enemy.PFS.GetBewegungspunktekostenReal(Field.X, Field.Y, Schlachtfeld)
            If Movecosts >= 0 And Movecosts <= Enemy.Unit.Bewegungspunkte And Enemy.Unit.Leben > 0 Then
                'Unit can reach our Position add it to Enemies!
                If Not Enemys.Contains(Enemy.Unit.Spieler) Then
                    Enemys.Add(Enemy.Unit.Spieler)
                End If
            End If
            'As said is this Unit an Indirect Unit and can attack this field?
            If Dis <= Enemy.Unit.GetMaximalReichweite(Wetter) And Dis > Enemy.Unit.MinimaleReichweite Then
                Score -= ScoreAttack(Enemy.Unit, Enemy.Unit.GetLocation, Field, Unit) 'Every
            End If
        Next


        'Are we a Unit that should be defended?
        If Not MeatwallUnit(Unit) Then

        End If




        Return Score
    End Function
#Region "Capturing"
    ''' <summary>
    ''' Scores how much points we get for capturing this Building.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Building"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreCapturing(ByVal Unit As ObjektEinheit, ByVal Building As ObjektGebaeude, ByVal PFS As Wegsuchsystem) As Double
        Dim Turns As Integer = TurnsLeftToCapture(Unit, Building)
        'We can finish our capture Phase in this Turn
        Dim BuildingValue As Integer = 1
        If Turns = 0 Then
            BuildingValue = 20
            Turns = 1
        End If
        Dim Score As Double = GetCaptureValue(Building, Unit) / Turns
        'A Headquarter is always very useful to own.
        If Building.Angriff = ObjektGebaeude.Angriffe.HQ Then
            Score += AIDatabase.HeadquarterValue
        End If
        If Building.Spieler = 0 Then
            Score += (AIDatabase.BuildingCaptureValue / Turns) * BuildingValue 'A neutral Building gets two Score Points
        Else
            'The higher the Priority for this Player is the higher the endscore
            Score += (AIDatabase.BuildingCaptureValue / Turns) * AIDatabase.GetPlayerData(Building.Spieler).PlayerPriority * BuildingValue
        End If
        Dim Dis As Integer = GetDistanceToFront(Building.Rechteck.X, Building.Rechteck.Y, Unit.Bewegungspunkte)
        If Dis <> 0 Then
            Score *= (1 + 1 / Dis)
        End If

        Return Score
    End Function
    ''' <summary>
    ''' How much Turns are left until this building is captured by the Unit.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Building"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function TurnsLeftToCapture(ByVal Unit As ObjektEinheit, ByVal Building As ObjektGebaeude, Optional ByVal HP As Integer = -1) As Integer
        If Unit.KannBesetzen Then
            If HP < 0 Then 'Load HP of this Unit
                HP = Unit.getKP
            End If
            'Unit capture Bonus
            HP += Unit.BesetzungsBonus
            'Get the Bonus for this Player
            Dim Bonus As Single = Objektverwalter.Spielfeld.Spieler(Unit.Spieler).KOS(0).Besetzer

            Dim BoostMode As Single = Unit.GetSpieler.KOS(0).GetKOZoneBoost(Unit)
            'If out of CO-Range the Bonus =0
            If BoostMode = 0 Then
                Bonus = 0
            Else
                Dim Bonus2 As Single = Math.Round(Bonus)
                'Calculate Bonus
                If Objektverwalter.Spielfeld.Regeln.KOSystem > KOSysteme.Gabe_Modus Then
                    'Should we add or multiply
                    If Bonus2 = Bonus Then
                        Bonus = 1 + Math.DivRem(CInt(Bonus - 1), CInt(1 / BoostMode), 0)
                    Else
                        Bonus *= BoostMode
                    End If
                Else
                    'Should we add or multiply
                    If Bonus2 = Bonus Then
                        Bonus = CInt(Bonus)
                    End If
                End If
            End If

            If Not Bonus = 0 Then
                Dim Bonus2 As Single = Math.Round(Bonus)
                'Multiply or add Bonus to HP
                If Bonus2 = Bonus Then
                    HP += Bonus
                Else
                    HP *= Bonus
                End If
            End If
            'Add Unit capture Bonus
            HP += Unit.BesetzungsBonus
            'Do we have a Capture Bonus for this Building
            Dim Bonussenkung As Integer = Objektverwalter.Spielfeld.Spieler(Unit.Spieler).KOS(0).GetBonusgebaeude(Building.Rechteck.X, Building.Rechteck.Y)
            If Bonussenkung >= 0 Then
                HP += Objektverwalter.Spielfeld.Spieler(Unit.Spieler).KOS(0).BonusGebaeude(Bonussenkung).Z
            End If
            'While Capture Points are higher 0 we need a second turn
            Dim TurnsLeft As Integer = 0
            Dim BuildingPoints As Integer = Building.Besetzung - HP
            If HP > 0 Then
                While BuildingPoints > 0
                    BuildingPoints -= HP
                    TurnsLeft += 1
                End While
            Else
                TurnsLeft = 3
            End If
            Return TurnsLeft
        End If
        Return -1 '-1 endless Turns left to capture
    End Function
    ''' <summary>
    ''' Get the Value of this Building
    ''' </summary>
    ''' <param name="Building"></param>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetCaptureValue(ByVal Building As ObjektGebaeude, ByVal Unit As ObjektEinheit) As Double
        'Get all Units that can be build here
        Dim PlayerList As String() = Building.GetBauliste(Unit.Spieler)
        Dim Fonds As Integer = 0
        'Loop through them and add the Costs of them to the Fonds
        For I = 0 To PlayerList.Length - 1
            Fonds += ObjektLadeklasse.NewEinheit(PlayerList(I), Unit.Spieler, -1, -1).Kosten * Spieler.Teurungsrate(Unit, Building.Rechteck.X, Building.Rechteck.Y)
        Next
        'Get the Average costs of all Units and Divide it through a Value that may be caluclated by the AI later on.
        If PlayerList.Length > 0 Then
            Return Fonds / (PlayerList.Length * AIDatabase.ProductionValue)
        End If
        Return 0
    End Function
#End Region
#Region "Attacking"
    ''' <summary>
    ''' We score the Attack we can do from here.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <param name="Target"></param>
    ''' <remarks></remarks>
    Private Function ScoreAttack(ByVal Unit As ObjektEinheit, ByVal Field As Point, ByVal Target As Point, Optional ByVal Enemy As ObjektEinheit = Nothing) As Double
        Dim Score As Double = 0

        Dim Damage As New PointF
        If Enemy Is Nothing Then
            'Get Enemy
            Enemy = Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap)
            Damage = GetVirtualAttack(Unit, Field, Target)
        Else
            Damage = GetVirtualAttack(Unit, Field, Target, Enemy)
        End If
        If Damage.X < 0 Then Damage.X = 0
        If Damage.Y < 0 Then Damage.Y = 0

        If Enemy IsNot Nothing Then
            'If Damage is bigger than our life reduce it to our Live
            If Unit.Leben - Damage.Y < 0 Then
                Damage.Y = Unit.Leben
                'We never kill our own Units, better use them as Meatwall
                Score -= 1000
            End If
            If Enemy.Leben - Damage.X < 0 Then
                Damage.X = Enemy.Leben
                Damage.Y = 0
                Score += Enemy.GetEinheitenWert / (Database.ThousandFonds)
            End If
            Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Enemy.X, Enemy.Y, Enemy.GetMap).Gebaeude
            Dim CaputeBonus As Single = 1
            If Building IsNot Nothing Then
                If Enemy.Besetzen And Building.IsBesetzung(Enemy) And Building.Besetzung > 0 Then
                    CaputeBonus = (TurnsLeftToCapture(Enemy, Building, getKP(Enemy.Leben - Damage.X)) + 1) / (TurnsLeftToCapture(Enemy, Building) + 1)
                    If CaputeBonus > 3 Then CaputeBonus = 3
                End If
            End If
            Dim EnemyData As Database.PlayerData = AIDatabase.GetPlayerData(Enemy.Spieler)
            Dim Distance As Integer = GetDistance(Field, Target)
            If Distance > 1 Then
                'Score calculation a little bit bigger.                                                                                                       Here i try to take into account the Unit values!
                Score += ((((CaputeBonus * Damage.X * EnemyData.PlayerPriority * AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.GeneralOffenceStrategy) - (Damage.Y)) / EnemyData.PlayerOffensiv) * (Enemy.GetEinheitenKosten / Database.ThousandFonds)) * (1 + Distance / 10)
            Else
                'Score calculation a little bit bigger.                                                                                                       Here i try to take into account the Unit values!
                Score += ((((CaputeBonus * Damage.X * EnemyData.PlayerPriority * AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.GeneralOffenceStrategy) - (Damage.Y)) / EnemyData.PlayerOffensiv) * (Enemy.GetEinheitenKosten / Unit.GetEinheitenKosten))
            End If
            'Half Score if Enemy is Weaponless as it is more effiecient to destroy Enemies with Ammo
            If Enemy.Munition = 0 And Enemy.Waffe2 <> "Keine" Then
                Score *= 0.5
            End If
        Else
            Dim Terrain As ObjektLandschaft = Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap)
            Dim Building As ObjektGebaeude = Terrain.Gebaeude
            If Building IsNot Nothing Then
                Score += (Damage.X * ObjektLadeklasse.GetGebaeudeKosten(Building.GebaeudeID, Building.Spieler) * AIDatabase.BuildingAttackValue) / (Building.GetMaxLeben * AIDatabase.GetPlayerData(Building.Spieler).PlayerOffensiv)
            Else
                Score += (Damage.X * AIDatabase.BuildingAttackValue) / Terrain.GetMaxLeben
            End If
        End If

        Return Score
    End Function
    ''' <summary>
    ''' Calaculate the Damage we do and get.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <param name="Target"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetVirtualAttack(ByVal Unit As ObjektEinheit, ByVal Field As Point, ByVal Target As Point) As PointF
        'X will be Damage and Y Counterdamage
        Dim Damage As PointF = New PointF(0, 0)
        Dim Enemy As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap)
        If Enemy IsNot Nothing Then
            'Calaculate Luck
            Dim OurLuck As Point = Spieler.GetGlueckPech(Field.X, Field.Y)
            'I think the Middle will be the most excat calculation
            OurLuck.X = (OurLuck.X + OurLuck.Y) / 2
            OurLuck.Y = OurLuck.Y
            Dim EnemyLuck As Point = Enemy.GetSpieler.GetGlueckPech(Target.X, Target.Y)
            EnemyLuck.X = (EnemyLuck.X + EnemyLuck.Y) / 2
            EnemyLuck.Y = EnemyLuck.Y
            Dim EnemyLive As Single = Enemy.Leben
            Damage.X = Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Enemy.X, Enemy.Y, Unit.Leben, EnemyLive, False, True, OurLuck.X, Enemy, False)(0)
            'Just save it in a new Value as it is used as Reference Value
            EnemyLive = Unit.Leben
            If EnemyLive > 0 And Distance(Field, Target) = 1 Then
                Damage.Y = Objektverwalter.Schadensberechnung(Enemy, Enemy.X, Enemy.Y, Field.X, Field.Y, Enemy.Leben - Damage.X, EnemyLive, True, True, EnemyLuck.X, Unit, False)(0)
            Else
                Damage.Y = 0
            End If
        Else
            Damage.X = Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, Unit.Leben, -1, False, False, -999, Nothing, False)(0)
        End If
        Return Damage
    End Function
    ''' <summary>
    ''' Calaculate the Damage we do and get.
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <param name="Target"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetVirtualAttack(ByVal Unit As ObjektEinheit, ByVal Field As Point, ByVal Target As Point, ByVal Enemy As ObjektEinheit) As PointF
        'X will be Damage and Y Counterdamage
        Dim Damage As PointF = New PointF(0, 0)
        If Enemy IsNot Nothing Then
            'Calaculate Luck
            Dim OurLuck As Point = Spieler.GetGlueckPech(Field.X, Field.Y)
            'I think the Middle will be the most excat calculation
            OurLuck.X = (OurLuck.X + OurLuck.Y) / 2
            OurLuck.Y = OurLuck.Y
            Dim EnemyLuck As Point = Enemy.GetSpieler.GetGlueckPech(Target.X, Target.Y)
            EnemyLuck.X = (EnemyLuck.X + EnemyLuck.Y) / 2
            EnemyLuck.Y = EnemyLuck.Y
            Dim EnemyLive As Single = Enemy.Leben
            Damage.X = Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Enemy.X, Enemy.Y, Unit.Leben, EnemyLive, False, True, OurLuck.X, Enemy, True)(0)
            'Just save it in a new Value as it is used as Reference Value
            EnemyLive = Unit.Leben
            If EnemyLive > 0 And Distance(Field, Target) = 1 Then
                Damage.Y = Objektverwalter.Schadensberechnung(Enemy, Enemy.X, Enemy.Y, Field.X, Field.Y, Enemy.Leben - Damage.X, EnemyLive, True, True, EnemyLuck.X, Unit, True)(0)
            Else
                Damage.Y = 0
            End If
        Else
            Damage.X = Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, Unit.Leben, -1, False, False, -999, Nothing, False)(0)
        End If
        Return Damage
    End Function
    ''' <summary>
    ''' Get all Fields we can attack from this Field!
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetAttackFields(ByVal Unit As ObjektEinheit, ByVal Field As Point) As List(Of Point)
        Dim Targets As New List(Of Point)
        Dim MaximalReichweite As Integer = -1
        Dim Kreis(,) As Integer
        'Load maximal Firerange
        MaximalReichweite = Unit.MaximaleReichweite
        'Inital Circle for Targets
        Kreis = Kreisfunktion(MaximalReichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                'Inside minimal Firerange?
                If Kreis(X, Y) >= Unit.MinimaleReichweite Then
                    Dim Fernkampf As Boolean = False
                    If Kreis(X, Y) > 1 Then
                        Fernkampf = True
                    End If
                    If CanAttackField(New Point(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y), Unit, Field, Fernkampf) Then
                        Targets.Add(New Point(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y))
                    End If
                ElseIf Not Unit.Waffe1 = "Keine" And Kreis(X, Y) > 0 Then
                    Dim Fernkampf As Boolean = False
                    If Kreis(X, Y) > 1 Then
                        Fernkampf = True
                    End If
                    If CanAttackField(New Point(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y), Unit, Field, Fernkampf) Then
                        Targets.Add(New Point(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y))
                    End If
                    'ElseIf Kreis(X, Y) = 0 Then
                    '    'Wir sind eine Lufteinheit
                    '    If Unit.GetMap = ObjektSpielfeld.Luftschlacht Then
                    '        If KannBodenAngriff(XPosition - MaximalReichweite + X, YPosition - MaximalReichweite + Y, XPosition, YPosition) Then
                    '            Targets.Add(New Point(Field.X - MaximalReichweite + X, Field.Y - MaximalReichweite + Y))
                    '        End If
                    '    End If
                End If
            Next
        Next
        Return Targets
    End Function
    ''' <summary>
    ''' Can we attack this Field?
    ''' </summary>
    ''' <param name="Target"></param>
    ''' <param name="Unit"></param>
    ''' <param name="Field"></param>
    ''' <param name="Indirect_Attack"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanAttackField(ByVal Target As Point, ByVal Unit As ObjektEinheit, ByVal Field As Point, ByVal Indirect_Attack As Boolean) As Boolean
        'On Map?
        If Objektverwalter.Spielfeld.OnMap(Target.X, Target.Y) Then
            'A Unit here?
            If IsNothing(Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap)) = False Then
                'enemy Unit?
                If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap).Spieler).Team = Unit.GetSpieler.Team Then
                    'Visible?
                    If Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap).Sichtbar = True Then
                        Dim Dis As Integer = GetDistance(Target.X, Target.Y, Field.X, Field.Y)
                        'Can we attack hidden Units?
                        If (Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap).IsGetaucht And Dis = 1 And Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap).Bewegungsart = Unit.Bewegungsart) Or Not Objektverwalter.Spielfeld.Einheiten(Target.X, Target.Y, Unit.GetMap).IsGetaucht Then
                            'Did we move?
                            If Unit.X = Field.X And Unit.Y = Field.Y Then
                                If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                    Return True
                                End If
                            ElseIf Indirect_Attack Then 'Indirect Attack
                                If Unit.CanIndirectMoveAndFire Then
                                    If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                        Return True
                                    End If
                                End If
                            Else
                                If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                    Return True
                                End If
                            End If
                        End If
                    End If
                End If
                'Do we want to attack a Terrain?
            ElseIf Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Leben > 0 Then
                'Did we move?
                If Unit.X = Field.X And Unit.Y = Field.Y Then
                    If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                        Return True
                    End If
                ElseIf Indirect_Attack Then 'Indirect Attack
                    If Unit.CanIndirectMoveAndFire Then
                        If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                            Return True
                        End If
                    End If
                Else
                    If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                        Return True
                    End If
                End If
                'Do we want to attack a building?
            ElseIf IsNothing(Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Gebaeude) = False Then
                If Objektverwalter.Spielfeld.Landschaften(Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Gebaeude.Rechteck.X, Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Gebaeude.Rechteck.Y, Unit.GetMap).Gebaeude.GetKP(Target.X, Target.Y, False) > 0 Then
                    If Not Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Landschaften(Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Gebaeude.Rechteck.X, Objektverwalter.Spielfeld.Landschaften(Target.X, Target.Y, Unit.GetMap).Gebaeude.Rechteck.Y, Unit.GetMap).Gebaeude.Spieler).Team = Unit.GetSpieler.Team Then
                        'Did we move?
                        If Unit.X = Field.X And Unit.Y = Field.Y Then
                            If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                Return True
                            End If
                        ElseIf Indirect_Attack Then 'Indirect Attack
                            If Unit.CanIndirectMoveAndFire Then
                                If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                    Return True
                                End If
                            End If
                        Else
                            If Objektverwalter.Schadensberechnung(Unit, Field.X, Field.Y, Target.X, Target.Y, 100, 100, False, False, -999, Nothing, False)(0) >= 0 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
#End Region
#End Region 'Wait Score Missing
#Region "Build"
    ''' <summary>
    ''' If the Build Score is lower than this we won't build the Unit.
    ''' </summary>
    ''' <remarks></remarks>
    Const MinBuildScore As Single = -5
    ''' <summary>
    ''' Scores that are that near are taken to be the same during Unit building process!
    ''' </summary>
    ''' <remarks></remarks>
    Const WIDE As Integer = 1
    Class AIBuilding
        Public Building As ObjektGebaeude
        Public ProductionList As String()
        Public PFSs As New List(Of Wegsuchsystem)

        ''' <summary>
        ''' The Score of this Unit!
        ''' </summary>
        ''' <remarks></remarks>
        Public Score As Single
        ''' <summary>
        ''' Units with the best Score
        ''' </summary>
        ''' <remarks></remarks>
        Public Units As List(Of ObjektEinheit)
        Public Sub New(ByVal Building As ObjektGebaeude, ByVal ProductionList As String(), ByVal Spieler As Integer)
            Me.Building = Building
            Me.ProductionList = ProductionList
            Units = New List(Of ObjektEinheit)
            For I2 = 0 To ProductionList.Length - 1
                'Get Unit of
                Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(ProductionList(I2), Spieler, Building.Rechteck.X, Building.Rechteck.Y)
                PFSs.Add(New Wegsuchsystem(Unit, Unit.X, Unit.Y, Schlachtfeld, -1, True, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren, True))
            Next
        End Sub
    End Class
    ''' <summary>
    ''' This Sub produces our Units!
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub BuildUnits()
        'Get all Buildings for our Production
        GetAllBuildings()
        'Sort all Buuildings out that are unable to build Units.
        Dim Buildings As New List(Of AIBuilding)
        For Each Building In Gebaeude
            If Objektverwalter.Spielfeld.Einheiten(Building.Rechteck.X, Building.Rechteck.Y, Schlachtfeld) Is Nothing Then
                Dim ProdList As String() = GetProducableUnits(Building.GetBaulisteThisPlayer, Building.Rechteck.X, Building.Rechteck.Y)
                If ProdList.Length > 0 Then
                    Buildings.Add(New AIBuilding(Building, ProdList, Spieler.Spieler))
                End If
            End If
        Next
        If Buildings.Count > 0 Then
            'Fonds we can spend because we spend less money on other Buildings.
            Dim ExtraFonds As Integer = Spieler.Fonds
            'Fonds we can spend on each Building so we produce on every single building a Unit
            Dim AverageSpendFonds As Integer = CalculateAverageFonds(Buildings, ExtraFonds)
            'Saving Infantry Costs for Spaming
            Dim InfantryCosts As Integer = Integer.MaxValue
            Dim InfantryID As String = ""
            For I = 0 To Buildings.Count - 1
                For I2 = 0 To Buildings(I).ProductionList.Length - 1
                    Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(Buildings(I).ProductionList(I2), Spieler.Spieler, -1, -1)
                    If Unit.KannBesetzen Then
                        Dim Value As Integer = Unit.GetEinheitenWert
                        If Value < InfantryCosts Then
                            InfantryCosts = Value
                            InfantryID = Unit.EinheitenID
                        End If
                    End If
                Next
            Next
            'We've calculated the cheapest Infantry Unit!
            Dim InfantrieFonds As Integer = 0
            If InfantryID <> "" Then
                If InfantryCosts < AverageSpendFonds Then
                    Dim Bases As Integer = 0
                    For Each Building In Buildings
                        If Building.ProductionList.Contains(InfantryID) Then
                            Bases += 1
                        End If
                    Next
                    InfantrieFonds = InfantryCosts * Bases
                Else
                    InfantryCosts = 0
                End If
            Else
                InfantryCosts = 0
            End If
            'Resort Buildings
            Buildings = SortBuildings(Buildings)
            'Not Attackable Units or Units we do very less Damage but need to be destroyed
            Dim UndestroyableUnits As New List(Of ObjektEinheit)
            'Get all our Units
            Dim OurUnits As List(Of ObjektEinheit) = GetUnits()
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Unit IsNot Nothing Then
                        'Enemy Unit?
                        If Unit.GetSpieler.Team <> Spieler.Team Then
                            'Loop through our Units.
                            For I = 0 To OurUnits.Count - 1
                                Dim Dmg As Single = GetDamage(OurUnits(I), Unit)
                                Dim CDmg As Single = GetDamage(Unit, OurUnits(I))
                                'Either the CDmg is very low and the Dmg at least greater 10 or our Damage is very big!
                                If Not Undestroyable(Dmg, CDmg, Unit.Leben) Then
                                    Exit For
                                ElseIf I = OurUnits.Count - 1 Then
                                    UndestroyableUnits.Add(Unit)
                                End If
                            Next
                        End If
                    End If
                Next
            Next
            'So now we know all Units we can build, we know where our Units can move and we know all Units we can't destroy
            'And we have sorted all Buildings so that the nearest Building is the first one.
            Dim Build As Boolean = True
            While Build And Buildings.Count > 0
                Build = False
                'Score all Buildings
                ScoreAllBuildings(Buildings, UndestroyableUnits, GetEnemyUnits, AverageSpendFonds, ExtraFonds, InfantrieFonds)
                Dim BestBuilding As New List(Of AIBuilding)
                BestBuilding.Add(Buildings(0))
                'Get Best Building!
                For I = 1 To Buildings.Count - 1
                    If BestBuilding(0).Score < Buildings(I).Score Then
                        BestBuilding.Clear()
                        BestBuilding.Add(Buildings(I))
                    ElseIf BestBuilding(0).Score = Buildings(I).Score Then
                        BestBuilding.Add(Buildings(I))
                    End If
                Next
                If BestBuilding.Count > 0 Then
                    If BestBuilding(0).Score > MinBuildScore Then
                        Dim Position As Integer = Zufallszahl(0, BestBuilding.Count - 1)
                        Dim Building As AIBuilding = BestBuilding(Position)
                        If Building.Units.Count > 0 Then
                            Dim Fonds As Integer = Spieler.Fonds
                            Dim Unit As ObjektEinheit = Building.Units(Zufallszahl(0, Building.Units.Count - 1))
                            GebaeudeAuswaehlen(KIModiExtern.EinheitBauen, Building.Building, Unit)
                            'So now we know how much fonds we've spend already!
                            Fonds -= Spieler.Fonds
                            ExtraFonds = AverageSpendFonds - Fonds
                            If InfantryID <> "" Then
                                If Building.ProductionList.Contains(InfantryID) Then
                                    InfantrieFonds -= InfantryCosts
                                End If
                            End If
                            Build = True
                            newUnitsArrived = True

                        End If
                        Buildings.RemoveAt(Position)
                    Else 'This Code forces the AI to spam Infantries!
                        For I = 0 To BestBuilding.Count - 1
                            If Objektverwalter.Spielfeld.Einheiten(BestBuilding(I).Building.Rechteck.X, BestBuilding(I).Building.Rechteck.Y, Schlachtfeld) Is Nothing Then
                                If BestBuilding(I).ProductionList.Contains(InfantryID) Then
                                    For I2 = 0 To BestBuilding(I).Units.Count - 1
                                        If BestBuilding(I).Units(I2).EinheitenID = InfantryID Then
                                            Dim Fonds As Integer = Spieler.Fonds
                                            Dim Unit As ObjektEinheit = BestBuilding(I).Units(I2)
                                            GebaeudeAuswaehlen(KIModiExtern.EinheitBauen, BestBuilding(I).Building, Unit)
                                            'So now we know how much fonds we've spend already!
                                            Fonds -= Spieler.Fonds
                                            ExtraFonds = AverageSpendFonds - Fonds
                                            InfantrieFonds -= InfantryCosts
                                            Build = True
                                            newUnitsArrived = True
                                            Buildings.RemoveAt(I)
                                            Exit For
                                        End If
                                    Next
                                    If Build Then Exit For
                                End If
                            End If
                        Next
                    End If
                End If
            End While
        End If
    End Sub
    ''' <summary>
    ''' Sorts the Buildings so that the nearest Building to an Enemy is the first Item.
    ''' </summary>
    ''' <param name="Buildings"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function SortBuildings(ByVal Buildings As List(Of AIBuilding)) As List(Of AIBuilding)
        Dim SortedBuildings As New List(Of AIBuilding)
        Dim DistanceToEnemys As New List(Of Single)
        For I = 0 To Buildings.Count - 1
            DistanceToEnemys.Add(Single.MinValue)
        Next
        'Loop through all fields
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).GetSpieler.Team <> Spieler.Team Then
                        'Here's an Enemy Unit
                        For I = 0 To Buildings.Count - 1
                            'Loop all Buildings
                            Dim AverageTurns As UInteger = 0
                            Dim UnitCount As UInteger = 0
                            'Loop all PFS's
                            For I2 = 0 To Buildings(I).PFSs.Count - 1
                                If Buildings(I).ProductionList.Contains(Buildings(I).PFSs(I2).Einheit.EinheitenID) Then
                                    'Get Movementpoints and increase Counter
                                    Dim MP As Integer = Buildings(I).PFSs(I2).GetBewegungspunktekostenReal(X, Y, Schlachtfeld)
                                    If MP >= 0 Then
                                        UnitCount += 1
                                        AverageTurns += MP
                                    End If
                                End If
                            Next
                            'If this was a moveable field check if it's nearer than the last one
                            If UnitCount > 0 Then
                                Dim Distance As Single = AverageTurns / UnitCount
                                If Distance >= 0 Then
                                    If Distance < DistanceToEnemys(I) Then
                                        DistanceToEnemys(I) = Distance
                                    ElseIf DistanceToEnemys(I) < 0 Then
                                        DistanceToEnemys(I) = Distance
                                    End If
                                End If
                            End If
                        Next
                    End If
                End If
            Next
        Next
        'Loop while not all Buildings are sorted
        While Buildings.Count > 0
            Dim SBuildings As New List(Of Integer)
            SBuildings.Add(0)
            'Get all Buildings with the lowest Distance
            Dim Nearest As Single = DistanceToEnemys(0)
            For I = 1 To Buildings.Count - 1
                If DistanceToEnemys(I) >= 0 Then
                    If DistanceToEnemys(I) < Nearest Then
                        SBuildings.Clear()
                        SBuildings.Add(I)
                        Nearest = DistanceToEnemys(I)
                    ElseIf DistanceToEnemys(I) = Nearest Then
                        SBuildings.Add(I)
                    End If
                ElseIf Nearest < 0 Then
                    SBuildings.Add(I)
                End If
            Next
            'Sort all Buildings with the lowest Distance at Random!
            While SBuildings.Count > 0
                Dim Rand As Integer = Zufallszahl(0, SBuildings.Count - 1)
                Dim MomBuilding As Integer = SBuildings(Rand)
                SortedBuildings.Add(Buildings(MomBuilding))
                'Reset SBuildings
                For I = 0 To SBuildings.Count - 1
                    If SBuildings(I) > MomBuilding Then
                        SBuildings(I) -= 1
                    End If
                Next
                Buildings.RemoveAt(MomBuilding)
                DistanceToEnemys.RemoveAt(MomBuilding)
                SBuildings.RemoveAt(Rand)
            End While
        End While
        Return SortedBuildings
    End Function
    ''' <summary>
    ''' Returns all Units we can build this turn with our maximal Fonds
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetProducableUnits(ByVal Bauliste() As String, ByVal X As Integer, ByVal Y As Integer) As String()
        Dim EinheitenIDs As New Stack(Of String)
        'Loop through Building list and look if we have enough Fonds and if we are allowed to build this Unit.
        For I = 0 To Bauliste.Length - 1
            If ObjektLadeklasse.GetEinheitenkosten(Bauliste(I)) * Spieler.Teurungsrate(Bauliste(I), X, Y) <= Spieler.Fonds Then
                If Spieler.GetBauliste Is Nothing Then
                    EinheitenIDs.Push(Bauliste(I))
                ElseIf Spieler.GetBauliste.GetWert(Bauliste(I)) >= 0 Then
                    EinheitenIDs.Push(Bauliste(I))
                End If
            End If
        Next
        Return EinheitenIDs.ToArray
    End Function
    ''' <summary>
    ''' Scores all Units that can be build on all Buildings!
    ''' </summary>
    ''' <param name="Buildings"></param>
    ''' <param name="UndestroyableUnits"></param>
    ''' <param name="EnemyUnits"></param>
    ''' <param name="AverageSpendFonds"></param>
    ''' <param name="ExtraFonds"></param>
    ''' <remarks></remarks>
    Private Sub ScoreAllBuildings(ByRef Buildings As List(Of AIBuilding), ByVal UndestroyableUnits As List(Of ObjektEinheit), ByVal EnemyUnits As List(Of ObjektEinheit), ByVal AverageSpendFonds As Integer, ByVal ExtraFonds As Integer, ByVal InfantryFonds As Integer)
        Dim DirectsToIndirects As Single = CalculateDirectsToIndirects()
        'Score each Building!
        For I0 = 0 To Buildings.Count - 1
            Buildings(I0).Score = Single.MinValue
            Buildings(I0).Units.Clear()
            If Objektverwalter.Spielfeld.Einheiten(Buildings(I0).Building.Rechteck.X, Buildings(I0).Building.Rechteck.Y, Schlachtfeld) Is Nothing Then
                For I1 = 0 To Buildings(I0).ProductionList.Length - 1
                    'Score all Units
                    Dim Unit As ObjektEinheit = ObjektLadeklasse.NewEinheit(Buildings(I0).ProductionList(I1), Spieler.Spieler, Buildings(I0).Building.Rechteck.X, Buildings(I0).Building.Rechteck.Y)
                    If Unit.GetEinheitenKosten <= Spieler.Fonds - InfantryFonds Then
                        Dim Score As Single = 0
                        For I2 = 0 To Buildings(I0).PFSs.Count - 1
                            If Buildings(I0).PFSs(I2).Einheit.EinheitenID = Unit.EinheitenID Then
                                If Unit.GetEinheitenKosten <= Spieler.Fonds Then
                                    Score = ScoreUnitBuild(Unit, Buildings(I0).PFSs(I2), UndestroyableUnits, EnemyUnits, AverageSpendFonds, ExtraFonds, DirectsToIndirects)
                                Else
                                    Score = Single.MinValue 'Not producable!
                                End If
                                Exit For
                            End If
                        Next
                        If Buildings(I0).Units.Count > 0 Then
                            'Save best Unit(s)
                            If Score < Buildings(I0).Score + WIDE And Score > Buildings(I0).Score - WIDE Then
                                Buildings(I0).Units.Add(Unit)
                                If Score > Buildings(I0).Score Then Buildings(I0).Score = Score
                            ElseIf Score > Buildings(I0).Score Then
                                Buildings(I0).Score = Score
                                Buildings(I0).Units.Clear()
                                Buildings(I0).Units.Add(Unit)
                            End If
                        Else
                            Buildings(I0).Score = Score
                            Buildings(I0).Units.Add(Unit)
                        End If
                    End If
                Next
            Else
                Buildings(I0).Score = Single.MinValue
            End If
        Next
    End Sub
    ''' <summary>
    ''' Scores how good it's to build this Unit.
    ''' </summary>
    ''' <param name="UndestroyableUnits"></param>
    ''' <param name="AverageSpendFonds"></param>
    ''' <param name="ExtraFonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreUnitBuild(ByVal Unit As ObjektEinheit, ByVal PFS As Wegsuchsystem, ByVal UndestroyableUnits As List(Of ObjektEinheit), ByVal EnemyUnits As List(Of ObjektEinheit), ByVal AverageSpendFonds As Integer, ByVal ExtraFonds As Integer, ByVal DirectsToIndirects As Single) As Single
        If Unit.HasNoWeapons Then
            'For the moment this gives a negativ Value!
            Return Single.MinValue
        Else
            Dim Score As Single = 0
            Dim MinTurns As Integer = Integer.MaxValue
            Dim MaxTurns As Integer = Integer.MinValue
            Dim NumberOfAttacks As Integer = 0
            Dim NumberOfStrongAttacks As Integer = 0
            Dim NumberOfWeakAttacks As Integer = 0
            For Each Enemy In EnemyUnits
                Dim R As Integer = 0
                Dim Turns As Integer = Math.DivRem(PFS.GetBewegungspunktekostenReal(Enemy.X, Enemy.Y, Schlachtfeld), Unit.Bewegungspunkte, R)
                If R <> 0 Then Turns += 1
                If Turns <= 0 Then Turns = 1
                If Turns > MaxTurns Then MaxTurns = Turns
                If Turns < MinTurns Then MinTurns = Turns
                Dim EnemyData As Database.PlayerData = AIDatabase.GetPlayerData(Enemy.Spieler)
                Dim DMG As Single = GetDamage(Unit, Enemy)
                If DMG < 0 Then DMG = 0
                If DMG > Enemy.Leben Then DMG = Enemy.Leben
                Dim CDMG As Single = GetDamage(Enemy, Unit)
                If CDMG < 0 Then CDMG = 0
                If CDMG > Unit.Leben Then CDMG = Unit.Leben
                Dim Multi As Single = 1
                For I = 0 To UndestroyableUnits.Count - 1
                    If UndestroyableUnits(I).EinheitenID = Enemy.EinheitenID And Not Undestroyable(DMG, CDMG, Enemy.Leben) Then
                        'Well we could fight against an undestroyable Unit? Great!
                        Multi += Unit.GetEinheitenKosten / (Database.ThousandFonds * 2)
                    End If
                Next
                'Indirect Attacks get a Bonus!
                If Unit.MinimaleReichweite > 1 Then
                    Multi += 1
                End If
                'Score depends on Distance and Value of the Unit!
                Dim Sum As Single = ((((DMG / 100) * EnemyData.PlayerPriority * AIDatabase.PlayerDatas(Enemy.Spieler - 1).AI_Strategy.GeneralOffenceStrategy * Enemy.GetEinheitenWert * Multi - ((CDMG / 100) * Unit.GetEinheitenWert) / EnemyData.PlayerOffensiv) / Database.ThousandFonds) / Turns)
                If Turns < AIDatabase.MinimalTurnDistance Then
                    Sum *= (1 + 1 / Turns)
                End If
                If (DMG > 50 And Unit.MinimaleReichweite = 1 Or DMG > 40 And Unit.MinimaleReichweite > 1) And Enemy.Kosten > AIDatabase.MechCosts Then
                    If Unit.MinimaleReichweite > 1 Then
                        Sum += (Enemy.Kosten / AIDatabase.MechCosts)
                    Else
                        If CDMG <= 0 Then
                            Sum += (Enemy.Kosten / AIDatabase.MechCosts)
                        Else
                            Sum += (Enemy.Kosten / AIDatabase.MechCosts) * (DMG / CDMG)
                        End If
                    End If
                    NumberOfStrongAttacks += 1
                Else
                    NumberOfWeakAttacks += 1
                End If
                If DMG > 10 Then NumberOfAttacks += 1
                Score += Sum
            Next
            If NumberOfStrongAttacks > 0 Then
                If NumberOfWeakAttacks > 0 Then
                    Score *= 1 + (NumberOfStrongAttacks / NumberOfWeakAttacks)
                Else
                    Score *= NumberOfStrongAttacks
                End If
            End If
            'Bonus or Antibonus for Directs\Indirects (not for Infantries)
            If Unit.GetEinheitenKosten > AIDatabase.MechCosts Then
                If DirectsToIndirects <> 0 Then
                    If Unit.MinimaleReichweite = 1 Then
                        Score /= DirectsToIndirects
                    Else
                        Score *= DirectsToIndirects
                    End If
                End If
            End If
            'Bonus for fast Moving
            If MinTurns > 0 And MaxTurns > 0 Then
                If MaxTurns - MinTurns > 0 Then
                    Score = (Score * Unit.Bewegungspunkte) / (MaxTurns - MinTurns)
                Else
                    Score = (Score * Unit.Bewegungspunkte)
                End If
            End If
            'Disadvantage for less Attacks
            If EnemyUnits.Count > 0 Then
                Score *= NumberOfAttacks / EnemyUnits.Count
            End If
            'Some pre calculations!
            Dim MoneyDifference As Integer = (Unit.GetEinheitenKosten - AverageSpendFonds - ExtraFonds) / Database.ThousandFonds
            Dim MoneyDifference2 As Integer = (Unit.GetEinheitenKosten - AverageSpendFonds) / Database.ThousandFonds
            'Those Units that either are around our current Average Fonds or increase our Fonds get extra Scores
            If (MoneyDifference > -WIDE And MoneyDifference < WIDE) Then
                Score += (Unit.GetEinheitenKosten / (Database.ThousandFonds * 2)) * 3 'Good Factor
            ElseIf MoneyDifference2 < 0 And (MoneyDifference2 >= -3) Then 'I would say 3000 is a good Score
                Score += Math.Abs(MoneyDifference2) * 3
            ElseIf MoneyDifference2 < -3 Then
                Score -= Math.Abs(MoneyDifference2) * 3
            ElseIf MoneyDifference > 0 Then 'To expansive bad!
                If MoneyDifference > AverageSpendFonds / Database.ThousandFonds Then
                    Return Single.MinValue
                Else
                    Score -= MoneyDifference * 3 'Bad Factor
                End If
            End If
            'Can we capture?
            If Unit.KannBesetzen Then
                Score += ScoreCaptureBuild(PFS, Unit)
                Score += ScoreNeutralCaptureBuild(Unit)
            End If


            Return Score
        End If
    End Function
    ''' <summary>
    ''' Checks if this Attack would clever!
    ''' </summary>
    ''' <param name="DMG"></param>
    ''' <param name="CDMG"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function Undestroyable(ByVal DMG As Single, ByVal CDMG As Single, ByVal EnemyLive As Single) As Boolean
        If Not ((CDMG <= 2 And DMG >= 10) Or DMG > 30 Or DMG >= EnemyLive) Then
            Return True
        End If
        Return False
    End Function
    ''' <summary>
    ''' We calculate the Score we get for capturing
    ''' </summary>
    ''' <param name="PFS"></param>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreCaptureBuild(ByVal PFS As Wegsuchsystem, ByVal Unit As ObjektEinheit) As Single
        Dim Score As Single = 0
        Dim Counter As Single = 0
        Dim MinTurns As Integer = Integer.MaxValue
        Dim MaxTurns As Integer = Integer.MinValue
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                If Building IsNot Nothing Then
                    If Building.GetSpieler.Team <> Spieler.Team Then
                        Dim CaptureUnit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                        If Building.IsBesetzung(Unit) Then
                            If CaptureUnit IsNot Nothing Then
                                If (CaptureUnit.GetSpieler.Team = Spieler.Team And CaptureUnit.KannBesetzen) Then
                                    Continue For
                                End If
                            End If
                            Dim R As Integer = 0
                            Dim Turns As Integer = Math.DivRem(PFS.GetBewegungspunktekostenReal(X, Y, Schlachtfeld), Unit.Bewegungspunkte, R)
                            If R <> 0 Then Turns += 1
                            If Turns <= 0 Then Turns = 1
                            If MinTurns > Turns Then MinTurns = Turns
                            If MaxTurns < Turns Then MaxTurns = Turns
                            Dim Owner As Integer = VirtualMap(X, Y).GetPlayerowner
                            If VirtualMap(X, Y).Influences(Spieler.Spieler - 1) = 0 Then
                                Score += Turns
                                Counter += 1
                            Else
                                If Owner + 1 = Spieler.Spieler Or GetDistanceToFront(PFS, X, Y) <= Unit.Bewegungspunkte Then
                                    Score += Turns
                                    Counter += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If Counter > 0 Then
            Score /= Counter
        End If
        If Score > 0 Then
            If MaxTurns - MinTurns > 0 Then
                Return (Score * Unit.Bewegungspunkte) / (MaxTurns - MinTurns)
            Else
                Return (Score * Unit.Bewegungspunkte)
            End If
        Else
            Return 0
        End If
    End Function
    ''' <summary>
    ''' We calculate the Score we get for capturing
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreNeutralCaptureBuild(ByVal Unit As ObjektEinheit) As Single
        Dim Score As Single = 0
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                Dim Building As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                If Building IsNot Nothing Then
                    If Building.Spieler = 0 Then
                        If Building.IsBesetzung(Unit) Then
                            Score += 1
                        End If
                    End If
                End If
            Next
        Next
        Return Score / (Objektverwalter.Spielfeld.Spieler.Length - 1)
    End Function
    ''' <summary>
    ''' Calculates the Average Fonds we can spend per Building!
    ''' </summary>
    ''' <param name="Buildings"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CalculateAverageFonds(ByVal Buildings As List(Of AIBuilding), ByRef ExtraFonds As Integer) As Integer
        Dim BuildingCount As Integer = 0
        Dim Average1 As Integer = Spieler.Fonds / Buildings.Count
        For Each Building In Buildings
            For Each UnitID In Building.ProductionList
                If ObjektLadeklasse.NewEinheit(UnitID, Spieler.Spieler, Building.Building.Rechteck.X, Building.Building.Rechteck.Y).GetEinheitenKosten < Average1 * 2 Then
                    BuildingCount += 1
                    Exit For
                End If
            Next
        Next
        If BuildingCount > 0 Then
            Average1 = Spieler.Fonds / BuildingCount
        End If
        ExtraFonds = Spieler.Fonds - Average1 * BuildingCount
        Return Average1
    End Function

    ''' <summary>
    ''' Calculates the Value between Directs and Indirects!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CalculateDirectsToIndirects() As Single
        Dim Units As List(Of ObjektEinheit) = GetUnits()
        Dim Directs As Integer = 0
        Dim Indirects As Integer = 0
        Dim DirectBonus As Single = GetDirectUnitBonus()
        Dim IndirectBonus As Single = GetIndirectUnitBonus()
        For I = 0 To Units.Count - 1
            If Units(I).Kosten > AIDatabase.MechCosts Then
                If Units(I).MaximaleReichweite = 1 And Units(I).MinimaleReichweite = 1 Or Units(I).Waffe1.ToUpper <> "KEINE" Then
                    Directs += 1
                End If
                If Units(I).MinimaleReichweite > 1 Then
                    Indirects += 1
                End If
            End If
        Next
        Directs *= DirectBonus
        Indirects *= IndirectBonus
        If Indirects > 0 Then
            Return Directs / Indirects
        Else
            Return Directs
        End If
    End Function


#End Region 'done
#Region "CO Power"
    ''' <summary>
    ''' Selects which Power we should use now!
    ''' </summary>
    ''' <remarks></remarks>
    Private Function UseCOPower(ByVal FirstTurnMove As Boolean) As Boolean
        Dim KO1 As ObjektKO.Gabemodi = CanUseCOPower(0, FirstTurnMove)
        Dim KO2 As ObjektKO.Gabemodi = ObjektKO.Gabemodi.Keine
        If Spieler.KOS(1) IsNot Nothing Then
            KO2 = CanUseCOPower(1, FirstTurnMove)
        End If
        If KO1 = ObjektKO.Gabemodi.Spezialgabe And KO2 = ObjektKO.Gabemodi.Spezialgabe Then
            If Spieler.KOS(1).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.RundenEnde And Spieler.KOS(0).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.Beides Then
            ElseIf Spieler.KOS(1).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.RundenEnde And Spieler.KOS(0).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.RundenAnfang Then
            ElseIf Spieler.KOS(0).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.RundenEnde And KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen Then
                Spieler.KOS(0).Doppelgabe()
                Return True
            ElseIf Spieler.KOS(0).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.RundenAnfang And KIModusIntern = KIModiIntern.KIStart Then
                'Die Doppelgabe kommt euer untergang ist nah Muahaha
                Spieler.KOS(0).Doppelgabe()
                Return True
            ElseIf Spieler.KOS(0).GabeEinsatzstelle = ObjektKO.KIGabeEinsatzstellen.Beides Then
                Spieler.KOS(0).Doppelgabe()
                Return True
            End If
        ElseIf KO1 = ObjektKO.Gabemodi.Spezialgabe And Spieler.KOS(1) IsNot Nothing Then
            If Spieler.KOS(1).Gabeleiste <= (Spieler.KOS(1).SpezialgabeKosten + Spieler.KOS(1).Gabekosten) * Spieler.KOS(1).Sternkosten - Spieler.KOS(1).Sternkosten * 3 Then
                Select Case Spieler.KOS(0).GabeEinsatzstelle
                    Case ObjektKO.KIGabeEinsatzstellen.RundenAnfang
                        If KIModusIntern = KIModiIntern.KIStart Then
                            'Die KI setzt die Spezialgabe ein
                            If Spieler.KOS(0).KannSpezialGabe Then
                                Spieler.KOS(0).Spezialgabe()
                                Return True
                            End If
                        End If
                    Case ObjektKO.KIGabeEinsatzstellen.RundenEnde
                        If KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen Then
                            'Die KI setzt die Spezialgabe ein
                            If Spieler.KOS(0).KannSpezialGabe Then
                                Spieler.KOS(0).Spezialgabe()
                                Return True
                            End If
                        End If
                    Case ObjektKO.KIGabeEinsatzstellen.Beides
                        'Die KI setzt die Spezialgabe ein
                        If Spieler.KOS(0).KannSpezialGabe Then
                            Spieler.KOS(0).Spezialgabe()
                            Return True
                        End If
                End Select
            End If
        ElseIf KO1 = ObjektKO.Gabemodi.Spezialgabe Then
            Spieler.KOS(0).Spezialgabe()
            Return True
        ElseIf KO1 = ObjektKO.Gabemodi.Gabe Then
            Spieler.KOS(0).Gabe()
            Return True
        End If
        Return False
    End Function
    ''' <summary>
    ''' Checks if we should use a Power
    ''' </summary>
    ''' <param name="KO"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CanUseCOPower(ByVal KO As Integer, ByVal FirstTurnMove As Boolean) As ObjektKO.Gabemodi
        If Spieler.VeraenderteWerte.Gabeeinsatz = True Then
            Select Case Spieler.KOS(KO).KOID
                Case "ANDY"
                    If Not FirstTurnMove Then
                        Dim Score As Single = Single.MinValue
                        Dim Score2 As Single = Single.MinValue
                        If Spieler.KOS(KO).KannGabe Then
                            Score = ScoreHealing(2) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                        End If
                        If Spieler.KOS(KO).KannSpezialGabe Then
                            Score2 = ScoreHealing(5)
                            If KO = 0 Then
                                Score2 += ScoreUnitBoost(KO)
                            Else
                                '=.5 for Fire Boost and 0.5 for Movement Boost
                                Score2 += 1
                            End If
                        End If
                        If Score > 0.4 Or Score2 > 1.2 Then
                            If Score > Score2 - 1 Then
                                Return ObjektKO.Gabemodi.Gabe
                            Else
                                Return ObjektKO.Gabemodi.Spezialgabe
                            End If
                        End If
                    Else
                        Return ObjektKO.Gabemodi.Keine
                    End If
                Case "MAX"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreDirects(KO) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        Score2 = ScoreDirects(KO)
                    End If
                    If Score > 0.6 Or Score2 > 0.3 Then
                        If Score - 0.3 > Score2 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                Case "MAVERIK"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreHealing(1) + ScoreDamage(1, 2) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        '=.5 for Fire Boost and 0.5 for Movement Boost
                        Score2 = ScoreHealing(2) + ScoreDamage(2, 2)
                    End If
                    If Score > 1 Or Score2 >= 1.0 Then
                        If Score > Score2 - 1 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                Case "EAGLE"
                    'As Eagles COP changes radical in AW2 the AI needs to react on that!
                    If DataSettings.CommanderWarsGameModus = CommanderWarsGameModi.AdvanceWars2 Then
                        Dim Score As Single = 0
                        If Spieler.KOS(KO).KannGabe Then
                            Score = ScoreAirUnits(KO) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                        End If
                        If Score > 0.6 Then
                            Return ObjektKO.Gabemodi.Gabe
                        End If
                    End If
                    'All Units can move again! :)
                    If KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen Then
                        If HasTanks() Then
                            If Spieler.KOS(KO).KannSpezialGabe Then
                                Return ObjektKO.Gabemodi.Spezialgabe
                            ElseIf Spieler.KOS(KO).KannGabe And Not DataSettings.CommanderWarsGameModus = CommanderWarsGameModi.AdvanceWars2 Then
                                If Spieler.KOS(0).Gabeleiste <= (Spieler.KOS(0).Gabekosten + 1) * Spieler.KOS(0).Sternkosten Then
                                    Return ObjektKO.Gabemodi.Gabe
                                End If
                            End If
                        End If
                    End If
                Case "ADAM", "ADDER", "KANBEI", "GRIMM", "JUGGER", "JAKE", "HELMUT", "JAVIER"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreUnitBoost(KO) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        Score2 = ScoreUnitBoost(KO)
                    End If
                    If Score > 0.6 Or Score2 > 0.3 Then
                        If Score - 0.3 > Score2 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                Case "OLAF"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreWeatherChange(ObjektSpielfeld.Wetterarten.Schnee) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        Score2 = ScoreWeatherChange(ObjektSpielfeld.Wetterarten.Schnee) + ScoreDamage(2, 2)
                    End If
                    If Score > 0.6 Or Score2 > 1.2 Then
                        If Score > Score2 - 1 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                Case "DRAKE"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreDamage(1, 2) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        Score2 = ScoreWeatherChange(ObjektSpielfeld.Wetterarten.Regen) + ScoreDamage(2, 2)
                    End If
                    If Score > 0.6 Or Score2 > 1.2 Then
                        If Score > Score2 - 1 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                Case "JESS"
                    Dim Score As Single = Single.MinValue
                    Dim Score2 As Single = Single.MinValue
                    If Spieler.KOS(KO).KannGabe Then
                        Score = ScoreTanks(KO) - (Spieler.KOS(0).Gabeleiste / Spieler.KOS(0).Sternkosten - Spieler.KOS(0).Gabekosten) / Spieler.KOS(0).SpezialgabeKosten
                    End If
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        Score2 = ScoreTanks(KO)
                    End If
                    If Score > 0.6 Or Score2 > 0.3 Then
                        If Score > Score2 - 1 Then
                            Return ObjektKO.Gabemodi.Gabe
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    End If
                    'Case "COLIN"
                    'Case "HACHI"

                Case Else 'This is a simple logic just for CO's we don't have any Info about!
                    If Spieler.KOS(KO).KannSpezialGabe Then
                        If KO = 0 Then
                            Select Case Spieler.KOS(KO).GabeEinsatzstelle
                                Case ObjektKO.KIGabeEinsatzstellen.RundenAnfang
                                    If KIModusIntern = KIModiIntern.KIStart Then
                                        'Die KI setzt die Spezialgabe ein
                                        Return ObjektKO.Gabemodi.Spezialgabe
                                    End If
                                Case ObjektKO.KIGabeEinsatzstellen.RundenEnde
                                    If KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen Then
                                        'Die KI setzt die Spezialgabe ein
                                        Return ObjektKO.Gabemodi.Spezialgabe
                                    End If
                                Case ObjektKO.KIGabeEinsatzstellen.Beides
                                    'Die KI setzt die Spezialgabe ein
                                    Return ObjektKO.Gabemodi.Spezialgabe
                            End Select
                        Else
                            Return ObjektKO.Gabemodi.Spezialgabe
                        End If
                    ElseIf Spieler.KOS(KO).KannGabe Then
                        If Spieler.KOS(0).Gabeleiste > Spieler.KOS(0).Gabekosten * Spieler.KOS(0).Sternkosten And Spieler.KOS(0).Gabeleiste <= (Spieler.KOS(0).Gabekosten + 1) * Spieler.KOS(0).Sternkosten Then
                            Select Case Spieler.KOS(0).GabeEinsatzstelle
                                Case ObjektKO.KIGabeEinsatzstellen.RundenAnfang
                                    If KIModusIntern = KIModiIntern.KIStart Then
                                        'Die KI setzt die Spezialgabe ein
                                        Return ObjektKO.Gabemodi.Gabe
                                    End If
                                Case ObjektKO.KIGabeEinsatzstellen.RundenEnde
                                    If KIModusIntern = KIModiIntern.RundenEndeGabeEinsetzen Then
                                        'Die KI setzt die Spezialgabe ein
                                        Return ObjektKO.Gabemodi.Gabe
                                    End If
                                Case ObjektKO.KIGabeEinsatzstellen.Beides
                                    'Die KI setzt die Spezialgabe ein
                                    Return ObjektKO.Gabemodi.Gabe
                            End Select
                        End If
                    End If
            End Select
        Else
            Return ObjektKO.Gabemodi.Keine
        End If
    End Function
    ''' <summary>
    ''' Scores how effectiv it is to Heal with a Power!
    ''' </summary>
    ''' <param name="HP"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreHealing(ByVal HP As Integer) As Single
        Dim Healing As Single = 0
        Dim MissHealing As Single = 0
        Dim NumberOfHeals As Single = 0
        Dim Units As Single = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Unit.Spieler = Spieler.Spieler Then
                        Units += 1
                        If Unit.getKP < 10 Then
                            Dim Miss As Integer = Unit.getKP + HP - 10
                            Dim Heal As Integer = 0
                            Dim Multi As Integer = 1
                            If Miss < 0 Then
                                Heal = HP
                                Miss = 0
                                Multi = HP
                            Else
                                Heal = HP - Miss
                            End If
                            Healing += HP * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi
                            MissHealing += Miss * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi
                            NumberOfHeals += 1
                        Else
                            MissHealing += HP * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10))
                        End If
                    End If
                End If
            Next
        Next
        If MissHealing <> 0 Then
            Return (Healing * NumberOfHeals) / (MissHealing * Units) + NumberOfHeals / Units
        Else
            Return (Healing * NumberOfHeals)
        End If
    End Function
    ''' <summary>
    ''' Scores how efficient it's to do damage with a Power
    ''' </summary>
    ''' <param name="Damage1">Damge done by this COP</param>
    ''' <param name="Damage2">Damage done by SCOP</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreDamage(ByVal Damage1 As Integer, ByVal Damage2 As Integer) As Single
        Dim _Damage1 As Single = 0
        Dim _MissDamage1 As Single = 0
        Dim _Damage2 As Single = 0
        Dim _MissDamage2 As Single = 0
        Dim NumberOfDamages As Single = 0
        Dim Units As Single = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Unit.GetSpieler.Team <> Spieler.Team Then
                        Units += 1
                        If Unit.getKP > 1 Then
                            Dim Miss1 As Integer = Unit.getKP - Damage1
                            Dim DMG1 As Integer = 0
                            Dim Multi1 As Integer = 1

                            Dim Miss2 As Integer = Unit.getKP - Damage2
                            Dim DMG2 As Integer = 0
                            Dim Multi2 As Integer = 1

                            If Miss1 >= 1 Then
                                DMG1 = Damage1
                                Miss1 = 0
                                Multi1 = Damage1
                            Else
                                DMG1 = Damage1 + Miss1 - 1
                                Miss1 = Damage1 - DMG1
                            End If

                            If Miss2 >= 1 Then
                                DMG2 = Damage2
                                Miss2 = 0
                                Multi2 = Damage2
                            Else
                                DMG2 = Damage2 + Miss2 - 1
                                Miss2 = Damage2 - DMG2
                            End If


                            _Damage1 += DMG1 * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi1
                            _MissDamage1 += Miss1 * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi1

                            _Damage2 += Damage2 * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi2
                            _MissDamage2 += Miss2 * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10)) * Multi2

                            NumberOfDamages += 1
                        Else
                            _MissDamage1 += _Damage1 * (Unit.GetEinheitenKosten / (Database.ThousandFonds / 10))

                        End If
                    End If
                End If
            Next
        Next
        If _MissDamage1 <> 0 Then
            _Damage1 = (_Damage1 * NumberOfDamages) / (_MissDamage1 * Units)
        Else
            _Damage1 = (_Damage1 * NumberOfDamages)
        End If
        If _MissDamage2 <> 0 Then
            _Damage2 = (_Damage2 * NumberOfDamages) / (_MissDamage2 * Units)
        Else
            _Damage2 = (_Damage2 * NumberOfDamages)
        End If
        If Damage2 <> 0 Then
            Return Damage1 / Damage2
        Else
            Return Damage1
        End If
    End Function
    ''' <summary>
    ''' Scores how much Direct Units are effected!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreDirects(ByVal KO As Integer) As Single
        Dim Score As Single = 0
        Dim UnitCount As Integer = 0
        Dim Directs As Integer = 0
        Dim UnusedDirects As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    If Unit.Spieler = Spieler.Spieler Then
                        UnitCount += 1
                        If Unit.IsDirectUnit Then
                            If Unit.KannBesetzen = False Then
                                If Unit.HatsichBewegt = False Or KO = 1 Then
                                    Directs += 1
                                Else
                                    UnusedDirects += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If UnitCount > 0 Then
            Score = (Directs - UnusedDirects) / UnitCount
        ElseIf UnusedDirects = 0 Then
            Score = Directs
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Scores how much Infantries Units are effected!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreInfantries(ByVal KO As Integer) As Single
        Dim Score As Single = 0
        Dim UnitCount As Integer = 0
        Dim Directs As Integer = 0
        Dim UnusedDirects As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    If Unit.Spieler = Spieler.Spieler Then
                        UnitCount += 1
                        If Unit.KannBesetzen = True Then
                            If Unit.HatsichBewegt = False Or KO = 1 Then
                                Directs += 1
                            Else
                                UnusedDirects += 1
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If UnitCount > 0 Then
            Score = (Directs - UnusedDirects) / UnitCount
        ElseIf UnusedDirects = 0 Then
            Score = Directs
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Scores how much Tank Units are effected!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreTanks(ByVal KO As Integer) As Single
        Dim Score As Single = 0
        Dim UnitCount As Integer = 0
        Dim Directs As Integer = 0
        Dim UnusedDirects As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    If Unit.Spieler = Spieler.Spieler Then
                        UnitCount += 1
                        If Unit.IsGroundUnit Then
                            If Unit.KannBesetzen = False Then
                                If Unit.HatsichBewegt = False Or KO = 1 Then
                                    Directs += 1
                                Else
                                    UnusedDirects += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If UnitCount > 0 Then
            Score = (Directs - UnusedDirects) / UnitCount
        ElseIf UnusedDirects = 0 Then
            Score = Directs
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Scores how much Air Units are effected!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreAirUnits(ByVal KO As Integer) As Single
        Dim Score As Single = 0
        Dim UnitCount As Integer = 0
        Dim AirUnits As Integer = 0
        Dim UnusedAirUnits As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    If Unit.Spieler = Spieler.Spieler Then
                        UnitCount += 1
                        If Not Unit.HasNoWeapons Then
                            If Unit.IsFlyingUnit Then
                                If Unit.HatsichBewegt = False Or KO = 1 Then
                                    AirUnits += 1
                                Else
                                    UnusedAirUnits += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If UnitCount > 0 Then
            Score = (AirUnits - UnusedAirUnits) / UnitCount
        ElseIf UnusedAirUnits = 0 Then
            Score = AirUnits
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Scores how much Indirect Units are effected!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreIndirects(ByVal KO As Integer) As Single
        Dim Score As Single = 0
        Dim UnitCount As Integer = 0
        Dim Indirects As Integer = 0
        Dim UnusedIndirects As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Unit IsNot Nothing Then
                    If Unit.Spieler = Spieler.Spieler Then
                        UnitCount += 1
                        If Unit.IsIndirectUnit Then
                            If Unit.KannBesetzen = False Then
                                If Unit.HatsichBewegt = False Or KO = 1 Then
                                    Indirects += 1
                                Else
                                    UnusedIndirects += 1
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If UnitCount > 0 Then
            Score = (Indirects - UnusedIndirects) / UnitCount
        ElseIf UnusedIndirects = 0 Then
            Score = Indirects
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Scores how efficient it is to use a COP that improves all Units (Offensive\Deffensive\Movementboosts) 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreUnitBoost(ByVal KO As Integer) As Single
        Dim BoostUnits As Integer = 0
        Dim Units As Single = 0
        Dim UnusedBoostUnits As Integer = 0
        Dim Score As Single = 0
        'Loop all Units
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Unit.Spieler = Spieler.Spieler Then
                        'Count own Units
                        Units += 1
                        If Not Unit.HatsichBewegt Or KO = 1 Then
                            'Good to use if Unit can get our boost!
                            BoostUnits += 1
                        Else
                            UnusedBoostUnits += 1
                        End If
                    End If
                End If
            Next
        Next
        If Units > 0 Then
            Score = (BoostUnits - UnusedBoostUnits) / Units
        ElseIf UnusedBoostUnits = 0 Then
            Score = BoostUnits
        Else
            Score = 0
        End If
        Return Score
    End Function
    ''' <summary>
    ''' Checks if we have any Tanks to move used for Eagles SCOP, COP
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function HasTanks() As Boolean
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    Dim Unit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Unit.Spieler = Spieler.Spieler Then
                        If Not Unit.KannBesetzen Then
                            Return True
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' How the Weather change is scored!
    ''' </summary>
    ''' <param name="Weather"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ScoreWeatherChange(ByVal Weather As ObjektSpielfeld.Wetterarten) As Single
        If Objektverwalter.Spielfeld.Regeln.Wetter = Weather Then
            Return 0
        Else
            Return 0.6
        End If
    End Function
#End Region 'CO-Scripts Missing
#Region "Analyze"
    ''' <summary>
    ''' Returns the Damage we could do to this Unit!
    ''' </summary>
    ''' <param name="Attacker"></param>
    ''' <param name="Enemy"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetDamage(ByVal Attacker As ObjektEinheit, ByVal Enemy As ObjektEinheit) As Single
        Dim DEFLive As Single = Enemy.Leben
        Dim ATKLive As Single = Attacker.Leben
        Return Objektverwalter.Schadensberechnung(Attacker, Attacker.X, Attacker.Y, Enemy.X, Enemy.Y, ATKLive, DEFLive, False, False, -999, Enemy, True, True)(0)
    End Function
    ''' <summary>
    ''' Get All our Units as List of Unit
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetUnits() As List(Of ObjektEinheit)
        Dim Units As New List(Of ObjektEinheit)
        'Loop trhough fields and check player
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    'Our Unit?
                    If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Spieler = Spieler.Spieler Then
                        Units.Add(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld))
                    End If
                End If
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Get All Enemy Units as List of Unit
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetEnemyUnits() As List(Of ObjektEinheit)
        Dim Units As New List(Of ObjektEinheit)
        'Loop trhough fields and check player
        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) IsNot Nothing Then
                    'Enemy Unit?
                    If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).GetSpieler.Team <> Spieler.Team Then
                        Units.Add(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld))
                    End If
                End If
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Calculates the Distance from one point to another for this PFS!
    ''' </summary>
    ''' <param name="PFS"></param>
    ''' <param name="X1"></param>
    ''' <param name="Y1"></param>
    ''' <param name="X2"></param>
    ''' <param name="Y2"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetDistancePFS(ByVal PFS As Wegsuchsystem, ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer) As Integer
        Return Math.Abs(PFS.GetBewegungspunktekostenReal(X1, Y1, Schlachtfeld) - PFS.GetBewegungspunktekostenReal(X2, Y2, Schlachtfeld))
    End Function
#End Region
#Region "CO Specific"
    ''' <summary>
    ''' Scores if we should have more directs or indirects
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetDirectUnitBonus() As Single
        Select Case Spieler.KOS(0).KOID
            Case "MAX"
                Return 0.3
            Case "KID", "SMITAN"
                Return 3
            Case "TAMI"
                Return 2
            Case "GRIMM"
                Return 1
            Case "IK-486-B7"
                Return 0.3
            Case Else
                Return 0.6
        End Select
    End Function
    ''' <summary>
    ''' Scores if we should have more directs or indirects
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetIndirectUnitBonus() As Single
        Select Case Spieler.KOS(0).KOID
            Case "KID", "SMITAN"
                Return 0.5
            Case "TAMI"
                Return 0.7
            Case "MAX"
                Return 3
            Case "GRIMM"
                Return 0.8
            Case "IK-486-B7"
                Return 2.5
            Case Else
                Return 1
        End Select
    End Function
#End Region 'CO's Missing
End Class
''' <summary>
''' Holding several Data about this Game used to calculate different Values better!
''' Used by the Heavy AI.
''' </summary>
''' <remarks></remarks>
Public Class Database
    ''' <summary>
    ''' Decides at which HP units are target as Low HP Units
    ''' </summary>
    ''' <remarks></remarks>
    Public LowHPUnit As Integer = 45
    ''' <summary>
    ''' If True the AI reads thr Balance Values out of a Textfile
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Text_Based_Strategy As Boolean = False
    ''' <summary>
    ''' The AI to which the Database belongs!
    ''' </summary>
    ''' <remarks></remarks>
    Dim AI As AI_Heavy
    ''' <summary>
    ''' The higher this Value the more the AI prefers to Attack in the Order Directs->Tanks->Infantries
    ''' </summary>
    ''' <remarks></remarks>
    Public TurnPriority As Single = 3.5
    ''' <summary>
    ''' Well it would be possible to spend 1 Fonds for an Infantry etc. so we reduce the big Values to Scoreable points by this
    ''' </summary>
    ''' <remarks></remarks>
    Public Const ThousandFonds As Integer = 1000
    ''' <summary>
    ''' The Influence Range of Buildings
    ''' </summary>
    ''' <remarks></remarks>
    Public Building_Influence As Integer = 4
    ''' <summary>
    ''' The Cost of Mech
    ''' </summary>
    ''' <remarks></remarks>
    Public MechCosts As Integer = 3000
    ''' <summary>
    ''' We divide Score calculations based on Fonds through this Value
    ''' </summary>
    ''' <remarks></remarks>
    Public LowGeneralFondsDivider As Integer = 300
    ''' <summary>
    ''' We divide Score calculations based on Fonds through this Value
    ''' </summary>
    ''' <remarks></remarks>
    Public BigGeneralFondsDivider As Integer = 1000
    ''' <summary>
    ''' The lower this Value the better the AI thinks it is to capture Bases or Airports
    ''' </summary>
    ''' <remarks></remarks>
    Public ProductionValue As Integer = 3000
    ''' <summary>
    ''' How important it's to own Headquarter compared to over structures.
    ''' </summary>
    ''' <remarks></remarks>
    Public HeadquarterValue As Single = 1.5
    ''' <summary>
    ''' The Higher the more Buildings will be captured by the AI.
    ''' </summary>
    ''' <remarks></remarks>
    Public BuildingCaptureValue As Integer = 8
    ''' <summary>
    ''' This calculates how efficient it is to attack Buildings
    ''' </summary>
    ''' <remarks></remarks>
    Public BuildingAttackValue As Integer = 4
    ''' <summary>
    ''' The greater this Value the more Score points we get for near Units during Building!
    ''' </summary>
    ''' <remarks></remarks>
    Public MinimalTurnDistance As Integer = 4
    ''' <summary>
    ''' The Data of all other Players.
    ''' </summary>
    ''' <remarks></remarks>
    Public PlayerDatas As New List(Of PlayerData)
    ''' <summary>
    ''' This Database is loaded for this Player
    ''' </summary>
    ''' <param name="Player"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Player As ObjektSpieler, ByVal AI As AI_Heavy)
        Me.AI = AI
        'Loop through all Players
        For I = 1 To Objektverwalter.Spielfeld.Spieler.Length - 1
            'If we're not this Player create new Data.
            PlayerDatas.Add(New PlayerData(Objektverwalter.Spielfeld.Spieler(I).Spieler))
        Next
        MechCosts = ObjektLadeklasse.NewEinheit("MECH", 1, -1, -1).GetEinheitenKosten
    End Sub
    ''' <summary>
    ''' Get The Data of a specific Player
    ''' </summary>
    ''' <param name="Player"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetPlayerData(ByVal Player As Integer) As PlayerData
        For I = 0 To PlayerDatas.Count - 1
            If PlayerDatas(I).Player = Player Then
                Return PlayerDatas(I)
            End If
        Next
        Return New PlayerData(0)
    End Function
    ''' <summary>
    ''' The Data used to represent a Player
    ''' </summary>
    ''' <remarks></remarks>
    Public Class PlayerData
        ''' <summary>
        ''' The Higher the more Units and the more Aggresiv we attack this Player compared to other Players.
        ''' And other Calculations may result in more Units that are effectiv against this player.
        ''' </summary>
        ''' <remarks></remarks>
        Public PlayerPriority As Double = 1
        ''' <summary>
        ''' The smaller this Value the more Offensiv we react on this Player.
        ''' </summary>
        ''' <remarks></remarks>
        Public PlayerOffensiv As Double = 5
        ''' <summary>
        ''' The Player whose Data are saved here.
        ''' </summary>
        ''' <remarks></remarks>
        Public Player As Integer = -1
        ''' <summary>
        ''' The number of Rounds this Player may have next Turn
        ''' E.G.: Tag Power=2
        ''' </summary>
        ''' <remarks></remarks>
        Public PlayerMoves As Integer = 1
        ''' <summary>
        ''' The AI Strategy for this Player
        ''' </summary>
        ''' <remarks></remarks>
        Public AI_Strategy As Player_AI_Strategy
        ''' <summary>
        ''' Structure for the current AI Strategy
        ''' </summary>
        ''' <remarks></remarks>
        Public Structure Player_AI_Strategy
            Enum Strategy
                Deffensive
                Standard
                Offensive
            End Enum
            Public Current_Strategy As Strategy
            ''' <summary>
            ''' The higher this Value the more Aggresiv we react in a General way, reduces the Value of our own Units in Damagecalculation.
            ''' </summary>
            ''' <remarks></remarks>
            Public GeneralOffenceStrategy As Double
            ''' <summary>
            ''' The lower this Value the more Defensiv Acts the AI when surrounded by a lot of Units
            ''' </summary>
            ''' <remarks></remarks>
            Public NextTurnDeffenceStrategy As Single
            ''' <summary>
            ''' The higher this Value the more will the AI use Meatwall Units to protect own Units!
            ''' </summary>
            ''' <remarks></remarks>
            Public MeatWallBonus As Double
            Public Sub New(ByVal Strategy As Strategy)
                Select Case Strategy
                    Case Player_AI_Strategy.Strategy.Offensive
                        Load_Offensive_Strategy()
                    Case Player_AI_Strategy.Strategy.Standard
                        Load_Standard_Strategy()
                    Case Else
                        Load_Deffensive_Strategy()
                End Select
                Current_Strategy = Strategy
            End Sub
            Public Sub LoadStrategy(ByVal Strategy As Strategy)
                Select Case Strategy
                    Case Player_AI_Strategy.Strategy.Offensive
                        Load_Offensive_Strategy()
                    Case Player_AI_Strategy.Strategy.Standard
                        Load_Standard_Strategy()
                    Case Else
                        Load_Deffensive_Strategy()
                End Select
                Current_Strategy = Strategy
            End Sub
            ''' <summary>
            ''' Set the Tactic to Offensiv to this Player.
            ''' </summary>
            ''' <remarks></remarks>
            Private Sub Load_Offensive_Strategy()
                GeneralOffenceStrategy = 1.8#
                NextTurnDeffenceStrategy = 1.0#
                MeatWallBonus = 2.5#
                If Database.Text_Based_Strategy And My.Computer.FileSystem.FileExists(My.Application.Info.DirectoryPath + "\AI_Heavy.ini") Then
                    Using StrR As New IO.StreamReader(My.Application.Info.DirectoryPath + "\AI_Heavy.ini", Hauptmenue.Codierung)
                        While Not StrR.EndOfStream
                            Dim Line As String = StrR.ReadLine
                            If Line.ToLower.StartsWith("OFFENSIV_GeneralOffenceStrategy:".ToLower) Then
                                GeneralOffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("OFFENSIV_NextTurnDeffenceStrategy:".ToLower) Then
                                NextTurnDeffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("OFFENSIV_MeatWallBonus:".ToLower) Then
                                MeatWallBonus = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                        End While
                    End Using
                End If
            End Sub
            ''' <summary>
            ''' Set the Tactic to Standard to this Player.
            ''' </summary>
            ''' <remarks></remarks>
            Private Sub Load_Standard_Strategy()
                GeneralOffenceStrategy = 1.6#
                NextTurnDeffenceStrategy = 0.9#
                MeatWallBonus = 2.8#
                If Database.Text_Based_Strategy And My.Computer.FileSystem.FileExists(My.Application.Info.DirectoryPath + "\AI_Heavy.ini") Then
                    Using StrR As New IO.StreamReader(My.Application.Info.DirectoryPath + "\AI_Heavy.ini", Hauptmenue.Codierung)
                        While Not StrR.EndOfStream
                            Dim Line As String = StrR.ReadLine
                            If Line.ToLower.StartsWith("DEFAULT_GeneralOffenceStrategy:".ToLower) Then
                                GeneralOffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("DEFAULT_NextTurnDeffenceStrategy:".ToLower) Then
                                NextTurnDeffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("DEFAULT_MeatWallBonus:".ToLower) Then
                                MeatWallBonus = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                        End While
                    End Using
                End If
            End Sub
            ''' <summary>
            ''' Set the Tactic to Defensiv to this Player.
            ''' </summary>
            ''' <remarks></remarks>
            Private Sub Load_Deffensive_Strategy()
                GeneralOffenceStrategy = 1.5#
                NextTurnDeffenceStrategy = 0.8#
                MeatWallBonus = 3.0#
                If Database.Text_Based_Strategy And My.Computer.FileSystem.FileExists(My.Application.Info.DirectoryPath + "\AI_Heavy.ini") Then
                    Using StrR As New IO.StreamReader(My.Application.Info.DirectoryPath + "\AI_Heavy.ini", Hauptmenue.Codierung)
                        While Not StrR.EndOfStream
                            Dim Line As String = StrR.ReadLine
                            If Line.ToLower.StartsWith("DEFFENSIV_GeneralOffenceStrategy:".ToLower) Then
                                GeneralOffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("DEFFENSIV_NextTurnDeffenceStrategy:".ToLower) Then
                                NextTurnDeffenceStrategy = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                            If Line.ToLower.StartsWith("DEFFENSIV_MeatWallBonus:".ToLower) Then
                                MeatWallBonus = CDbl(Line.Split(":")(1))
                                Continue While
                            End If
                        End While
                    End Using
                End If
            End Sub
        End Structure
        ''' <summary>
        ''' Creates the Player Data.
        ''' </summary>
        ''' <param name="Player"></param>
        ''' <remarks></remarks>
        Public Sub New(ByVal Player As Integer)
            Me.Player = Player
            AI_Strategy = New Player_AI_Strategy(Player_AI_Strategy.Strategy.Deffensive)
        End Sub
    End Class
    ''' <summary>
    ''' Finds out which is the Highest Prio for a Player
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetHighestPlayerPrio() As Double
        Dim Prio As Double = 0
        For I = 0 To PlayerDatas.Count - 1
            If PlayerDatas(I).PlayerPriority > Prio Then
                Prio = PlayerDatas(I).PlayerPriority
            End If
        Next
        Return Prio
    End Function
    ''' <summary>
    ''' The Average Meatwall Bonus
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Get_Average_MeatWallBonus() As Double
        Dim MeatwallBonus As Double = 0
        For I = 0 To PlayerDatas.Count - 1
            If PlayerDatas(I).Player <> AI.Spieler.Spieler Then
                MeatwallBonus += PlayerDatas(I).AI_Strategy.MeatWallBonus
            End If
        Next
        Return MeatwallBonus / (PlayerDatas.Count - 1)
    End Function
    ''' <summary>
    ''' The Average Meatwall Bonus
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Get_Average_MeatWallBonus(ByVal Players As List(Of Integer)) As Double
        Dim MeatwallBonus As Double = 0
        For I = 0 To Players.Count - 1
            If Players(I) > 0 And Players(I) <= PlayerDatas.Count Then
                MeatwallBonus += PlayerDatas(Players(I) - 1).AI_Strategy.MeatWallBonus
            End If
        Next
        Return MeatwallBonus / (PlayerDatas.Count - 1)
    End Function
    ''' <summary>
    ''' The Average Next Turn Deffence Strategy
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Get_Average_Next_Turn_Deffence_Strategy() As Single
        Dim NextTurnDeffenceStrategy As Single = 0
        For I = 0 To PlayerDatas.Count - 1
            If PlayerDatas(I).Player <> AI.Spieler.Spieler Then
                NextTurnDeffenceStrategy += PlayerDatas(I).AI_Strategy.NextTurnDeffenceStrategy
            End If
        Next
        Return NextTurnDeffenceStrategy / (PlayerDatas.Count - 1)
    End Function
End Class